From 40b02e4d95dec063fead12d6cffc0cc13e102067 Mon Sep 17 00:00:00 2001 From: kamhung <22250530@qq.com> Date: Wed, 9 Dec 2015 10:20:55 +0800 Subject: [PATCH] --- src/com/wentch/redkale/boot/Application.java | 566 ------ src/com/wentch/redkale/boot/ClassFilter.java | 436 ----- .../wentch/redkale/boot/LogFileHandler.java | 267 --- .../wentch/redkale/boot/NodeHttpServer.java | 133 -- src/com/wentch/redkale/boot/NodeProtocol.java | 19 - src/com/wentch/redkale/boot/NodeServer.java | 442 ----- .../wentch/redkale/boot/NodeSncpServer.java | 69 - .../wentch/redkale/convert/AnyEncoder.java | 40 - .../wentch/redkale/convert/ArrayDecoder.java | 79 - .../wentch/redkale/convert/ArrayEncoder.java | 75 - .../redkale/convert/CollectionDecoder.java | 69 - .../redkale/convert/CollectionEncoder.java | 65 - src/com/wentch/redkale/convert/Convert.java | 26 - .../wentch/redkale/convert/ConvertColumn.java | 44 - .../redkale/convert/ConvertColumnEntry.java | 67 - .../redkale/convert/ConvertColumns.java | 24 - .../wentch/redkale/convert/ConvertEntity.java | 25 - .../redkale/convert/ConvertException.java | 28 - .../wentch/redkale/convert/ConvertType.java | 28 - src/com/wentch/redkale/convert/DeMember.java | 64 - .../wentch/redkale/convert/Decodeable.java | 27 - src/com/wentch/redkale/convert/EnMember.java | 76 - .../wentch/redkale/convert/Encodeable.java | 27 - src/com/wentch/redkale/convert/Factory.java | 385 ---- src/com/wentch/redkale/convert/HashedMap.java | 70 - .../wentch/redkale/convert/MapDecoder.java | 78 - .../wentch/redkale/convert/MapEncoder.java | 62 - .../wentch/redkale/convert/ObjectDecoder.java | 157 -- .../wentch/redkale/convert/ObjectEncoder.java | 233 --- src/com/wentch/redkale/convert/Reader.java | 112 -- .../wentch/redkale/convert/SimpledCoder.java | 42 - src/com/wentch/redkale/convert/Writer.java | 120 -- .../convert/bson/BsonByteBufferWriter.java | 134 -- .../redkale/convert/bson/BsonConvert.java | 155 -- .../redkale/convert/bson/BsonFactory.java | 62 - .../redkale/convert/bson/BsonReader.java | 322 ---- .../convert/bson/BsonSimpledCoder.java | 17 - .../redkale/convert/bson/BsonWriter.java | 297 ---- .../convert/ext/BigIntegerSimpledCoder.java | 38 - .../convert/ext/BoolArraySimpledCoder.java | 68 - .../redkale/convert/ext/BoolSimpledCoder.java | 32 - .../convert/ext/ByteArraySimpledCoder.java | 68 - .../redkale/convert/ext/ByteSimpledCoder.java | 32 - .../convert/ext/CharArraySimpledCoder.java | 68 - .../redkale/convert/ext/CharSimpledCoder.java | 33 - .../convert/ext/DLongSimpledCoder.java | 40 - .../redkale/convert/ext/DateSimpledCoder.java | 33 - .../convert/ext/DoubleArraySimpledCoder.java | 68 - .../convert/ext/DoubleSimpledCoder.java | 32 - .../redkale/convert/ext/EnumSimpledCoder.java | 44 - .../convert/ext/FloatArraySimpledCoder.java | 68 - .../convert/ext/FloatSimpledCoder.java | 32 - .../convert/ext/InetAddressSimpledCoder.java | 70 - .../convert/ext/IntArraySimpledCoder.java | 68 - .../redkale/convert/ext/IntSimpledCoder.java | 32 - .../convert/ext/LongArraySimpledCoder.java | 68 - .../redkale/convert/ext/LongSimpledCoder.java | 33 - .../convert/ext/NumberSimpledCoder.java | 32 - .../convert/ext/PatternSimpledCoder.java | 38 - .../convert/ext/ShortArraySimpledCoder.java | 68 - .../convert/ext/ShortSimpledCoder.java | 32 - .../convert/ext/StringArraySimpledCoder.java | 68 - .../convert/ext/StringSimpledCoder.java | 32 - .../redkale/convert/ext/TypeSimpledCoder.java | 42 - .../json/InetAddressJsonSimpledCoder.java | 68 - .../convert/json/JsonByteBufferWriter.java | 348 ---- .../redkale/convert/json/JsonConvert.java | 137 -- .../redkale/convert/json/JsonFactory.java | 60 - .../redkale/convert/json/JsonReader.java | 576 ------ .../convert/json/JsonSimpledCoder.java | 17 - .../redkale/convert/json/JsonWriter.java | 268 --- src/com/wentch/redkale/net/Async.java | 25 - .../wentch/redkale/net/AsyncConnection.java | 570 ------ .../redkale/net/AsyncDatagramChannel.java | 1327 -------------- src/com/wentch/redkale/net/Context.java | 132 -- src/com/wentch/redkale/net/PrepareRunner.java | 98 -- .../wentch/redkale/net/PrepareServlet.java | 73 - .../wentch/redkale/net/ProtocolServer.java | 185 -- src/com/wentch/redkale/net/Request.java | 112 -- src/com/wentch/redkale/net/Response.java | 228 --- src/com/wentch/redkale/net/SSLBuilder.java | 160 -- src/com/wentch/redkale/net/Server.java | 188 -- src/com/wentch/redkale/net/Servlet.java | 27 - src/com/wentch/redkale/net/Transport.java | 254 --- src/com/wentch/redkale/net/WorkThread.java | 31 - .../wentch/redkale/net/http/AuthIgnore.java | 22 - .../redkale/net/http/BasedHttpServlet.java | 260 --- .../redkale/net/http/HttpCacheable.java | 25 - .../wentch/redkale/net/http/HttpContext.java | 59 - .../redkale/net/http/HttpPrepareServlet.java | 152 -- .../wentch/redkale/net/http/HttpRequest.java | 531 ------ .../redkale/net/http/HttpResourceServlet.java | 260 --- .../wentch/redkale/net/http/HttpResponse.java | 561 ------ .../wentch/redkale/net/http/HttpServer.java | 127 -- .../wentch/redkale/net/http/HttpServlet.java | 29 - src/com/wentch/redkale/net/http/MimeType.java | 240 --- .../wentch/redkale/net/http/MultiContext.java | 284 --- .../wentch/redkale/net/http/MultiPart.java | 115 -- .../wentch/redkale/net/http/WebAction.java | 22 - .../wentch/redkale/net/http/WebInitParam.java | 24 - .../wentch/redkale/net/http/WebServlet.java | 28 - .../wentch/redkale/net/http/WebSocket.java | 387 ---- .../redkale/net/http/WebSocketBinary.java | 23 - .../redkale/net/http/WebSocketEngine.java | 92 - .../redkale/net/http/WebSocketGroup.java | 128 -- .../redkale/net/http/WebSocketNode.java | 196 --- .../redkale/net/http/WebSocketPacket.java | 123 -- .../redkale/net/http/WebSocketRunner.java | 529 ------ .../redkale/net/http/WebSocketServlet.java | 145 -- .../redkale/net/sncp/ServiceWrapper.java | 92 - src/com/wentch/redkale/net/sncp/Sncp.java | 1108 ------------ src/com/wentch/redkale/net/sncp/SncpCall.java | 24 - .../wentch/redkale/net/sncp/SncpClient.java | 406 ----- src/com/wentch/redkale/net/sncp/SncpDyn.java | 24 - .../redkale/net/sncp/SncpDynServlet.java | 407 ----- .../wentch/redkale/net/sncp/SncpFuture.java | 94 - .../redkale/net/sncp/SncpPrepareServlet.java | 94 - .../wentch/redkale/net/sncp/SncpRemote.java | 23 - .../wentch/redkale/net/sncp/SncpRequest.java | 148 -- .../wentch/redkale/net/sncp/SncpResponse.java | 83 - .../wentch/redkale/net/sncp/SncpServer.java | 66 - .../wentch/redkale/net/sncp/SncpServlet.java | 32 - .../redkale/net/sncp/SncpTargetAddress.java | 24 - .../service/DataCacheListenerService.java | 41 - .../service/DataSQLListenerService.java | 118 -- .../redkale/service/DataSourceService.java | 341 ---- .../wentch/redkale/service/LocalService.java | 23 - src/com/wentch/redkale/service/MultiRun.java | 30 - src/com/wentch/redkale/service/RetResult.java | 113 -- src/com/wentch/redkale/service/Service.java | 43 - .../redkale/service/WebSocketNodeService.java | 76 - .../redkale/source/DataCacheListener.java | 21 - .../source/DataCallArrayAttribute.java | 57 - .../redkale/source/DataCallAttribute.java | 72 - .../wentch/redkale/source/DataConnection.java | 29 - .../redkale/source/DataDefaultSource.java | 1554 ----------------- .../redkale/source/DataSQLListener.java | 20 - src/com/wentch/redkale/source/DataSource.java | 244 --- .../redkale/source/DistributeGenerator.java | 44 - .../wentch/redkale/source/EntityCache.java | 654 ------- src/com/wentch/redkale/source/EntityInfo.java | 371 ---- src/com/wentch/redkale/source/FilterBean.java | 15 - .../wentch/redkale/source/FilterColumn.java | 46 - .../wentch/redkale/source/FilterExpress.java | 46 - .../wentch/redkale/source/FilterGroup.java | 62 - .../wentch/redkale/source/FilterGroups.java | 23 - .../redkale/source/FilterJoinColumn.java | 50 - .../wentch/redkale/source/FilterJoinNode.java | 315 ---- src/com/wentch/redkale/source/FilterNode.java | 958 ---------- .../wentch/redkale/source/FilterNodeBean.java | 353 ---- src/com/wentch/redkale/source/Flipper.java | 111 -- .../wentch/redkale/source/JDBCPoolSource.java | 238 --- src/com/wentch/redkale/source/Range.java | 284 --- src/com/wentch/redkale/source/ReckonType.java | 21 - .../wentch/redkale/source/VirtualEntity.java | 21 - src/com/wentch/redkale/util/AnyValue.java | 434 ----- src/com/wentch/redkale/util/Attribute.java | 323 ---- src/com/wentch/redkale/util/AutoLoad.java | 24 - src/com/wentch/redkale/util/ByteArray.java | 161 -- src/com/wentch/redkale/util/Creator.java | 207 --- src/com/wentch/redkale/util/DLong.java | 81 - .../redkale/util/DebugMethodVisitor.java | 150 -- src/com/wentch/redkale/util/Ignore.java | 22 - src/com/wentch/redkale/util/LogLevel.java | 24 - src/com/wentch/redkale/util/Nameable.java | 15 - src/com/wentch/redkale/util/ObjectNode.java | 26 - src/com/wentch/redkale/util/ObjectPool.java | 99 -- src/com/wentch/redkale/util/Reproduce.java | 132 -- .../wentch/redkale/util/ResourceFactory.java | 240 --- src/com/wentch/redkale/util/SelectColumn.java | 136 -- src/com/wentch/redkale/util/Sheet.java | 88 - src/com/wentch/redkale/util/TypeToken.java | 26 - src/com/wentch/redkale/util/Utility.java | 517 ------ .../wentch/redkale/watch/WatchFactory.java | 99 -- src/com/wentch/redkale/watch/WatchNode.java | 21 - src/com/wentch/redkale/watch/WatchNumber.java | 49 - .../wentch/redkale/watch/WatchSupplier.java | 47 - src/com/wentch/redkale/watch/Watchable.java | 34 - 178 files changed, 27401 deletions(-) delete mode 100644 src/com/wentch/redkale/boot/Application.java delete mode 100644 src/com/wentch/redkale/boot/ClassFilter.java delete mode 100644 src/com/wentch/redkale/boot/LogFileHandler.java delete mode 100644 src/com/wentch/redkale/boot/NodeHttpServer.java delete mode 100644 src/com/wentch/redkale/boot/NodeProtocol.java delete mode 100644 src/com/wentch/redkale/boot/NodeServer.java delete mode 100644 src/com/wentch/redkale/boot/NodeSncpServer.java delete mode 100644 src/com/wentch/redkale/convert/AnyEncoder.java delete mode 100644 src/com/wentch/redkale/convert/ArrayDecoder.java delete mode 100644 src/com/wentch/redkale/convert/ArrayEncoder.java delete mode 100644 src/com/wentch/redkale/convert/CollectionDecoder.java delete mode 100644 src/com/wentch/redkale/convert/CollectionEncoder.java delete mode 100644 src/com/wentch/redkale/convert/Convert.java delete mode 100644 src/com/wentch/redkale/convert/ConvertColumn.java delete mode 100644 src/com/wentch/redkale/convert/ConvertColumnEntry.java delete mode 100644 src/com/wentch/redkale/convert/ConvertColumns.java delete mode 100644 src/com/wentch/redkale/convert/ConvertEntity.java delete mode 100644 src/com/wentch/redkale/convert/ConvertException.java delete mode 100644 src/com/wentch/redkale/convert/ConvertType.java delete mode 100644 src/com/wentch/redkale/convert/DeMember.java delete mode 100644 src/com/wentch/redkale/convert/Decodeable.java delete mode 100644 src/com/wentch/redkale/convert/EnMember.java delete mode 100644 src/com/wentch/redkale/convert/Encodeable.java delete mode 100644 src/com/wentch/redkale/convert/Factory.java delete mode 100644 src/com/wentch/redkale/convert/HashedMap.java delete mode 100644 src/com/wentch/redkale/convert/MapDecoder.java delete mode 100644 src/com/wentch/redkale/convert/MapEncoder.java delete mode 100644 src/com/wentch/redkale/convert/ObjectDecoder.java delete mode 100644 src/com/wentch/redkale/convert/ObjectEncoder.java delete mode 100644 src/com/wentch/redkale/convert/Reader.java delete mode 100644 src/com/wentch/redkale/convert/SimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/Writer.java delete mode 100644 src/com/wentch/redkale/convert/bson/BsonByteBufferWriter.java delete mode 100644 src/com/wentch/redkale/convert/bson/BsonConvert.java delete mode 100644 src/com/wentch/redkale/convert/bson/BsonFactory.java delete mode 100644 src/com/wentch/redkale/convert/bson/BsonReader.java delete mode 100644 src/com/wentch/redkale/convert/bson/BsonSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/bson/BsonWriter.java delete mode 100644 src/com/wentch/redkale/convert/ext/BigIntegerSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/BoolArraySimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/BoolSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/ByteArraySimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/ByteSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/CharArraySimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/CharSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/DLongSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/DateSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/DoubleArraySimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/DoubleSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/EnumSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/FloatArraySimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/FloatSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/InetAddressSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/IntArraySimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/IntSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/LongArraySimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/LongSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/NumberSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/PatternSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/ShortArraySimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/ShortSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/StringArraySimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/StringSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/ext/TypeSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/json/InetAddressJsonSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java delete mode 100644 src/com/wentch/redkale/convert/json/JsonConvert.java delete mode 100644 src/com/wentch/redkale/convert/json/JsonFactory.java delete mode 100644 src/com/wentch/redkale/convert/json/JsonReader.java delete mode 100644 src/com/wentch/redkale/convert/json/JsonSimpledCoder.java delete mode 100644 src/com/wentch/redkale/convert/json/JsonWriter.java delete mode 100644 src/com/wentch/redkale/net/Async.java delete mode 100644 src/com/wentch/redkale/net/AsyncConnection.java delete mode 100644 src/com/wentch/redkale/net/AsyncDatagramChannel.java delete mode 100644 src/com/wentch/redkale/net/Context.java delete mode 100644 src/com/wentch/redkale/net/PrepareRunner.java delete mode 100644 src/com/wentch/redkale/net/PrepareServlet.java delete mode 100644 src/com/wentch/redkale/net/ProtocolServer.java delete mode 100644 src/com/wentch/redkale/net/Request.java delete mode 100644 src/com/wentch/redkale/net/Response.java delete mode 100644 src/com/wentch/redkale/net/SSLBuilder.java delete mode 100644 src/com/wentch/redkale/net/Server.java delete mode 100644 src/com/wentch/redkale/net/Servlet.java delete mode 100644 src/com/wentch/redkale/net/Transport.java delete mode 100644 src/com/wentch/redkale/net/WorkThread.java delete mode 100644 src/com/wentch/redkale/net/http/AuthIgnore.java delete mode 100644 src/com/wentch/redkale/net/http/BasedHttpServlet.java delete mode 100644 src/com/wentch/redkale/net/http/HttpCacheable.java delete mode 100644 src/com/wentch/redkale/net/http/HttpContext.java delete mode 100644 src/com/wentch/redkale/net/http/HttpPrepareServlet.java delete mode 100644 src/com/wentch/redkale/net/http/HttpRequest.java delete mode 100644 src/com/wentch/redkale/net/http/HttpResourceServlet.java delete mode 100644 src/com/wentch/redkale/net/http/HttpResponse.java delete mode 100644 src/com/wentch/redkale/net/http/HttpServer.java delete mode 100644 src/com/wentch/redkale/net/http/HttpServlet.java delete mode 100644 src/com/wentch/redkale/net/http/MimeType.java delete mode 100644 src/com/wentch/redkale/net/http/MultiContext.java delete mode 100644 src/com/wentch/redkale/net/http/MultiPart.java delete mode 100644 src/com/wentch/redkale/net/http/WebAction.java delete mode 100644 src/com/wentch/redkale/net/http/WebInitParam.java delete mode 100644 src/com/wentch/redkale/net/http/WebServlet.java delete mode 100644 src/com/wentch/redkale/net/http/WebSocket.java delete mode 100644 src/com/wentch/redkale/net/http/WebSocketBinary.java delete mode 100644 src/com/wentch/redkale/net/http/WebSocketEngine.java delete mode 100644 src/com/wentch/redkale/net/http/WebSocketGroup.java delete mode 100644 src/com/wentch/redkale/net/http/WebSocketNode.java delete mode 100644 src/com/wentch/redkale/net/http/WebSocketPacket.java delete mode 100644 src/com/wentch/redkale/net/http/WebSocketRunner.java delete mode 100644 src/com/wentch/redkale/net/http/WebSocketServlet.java delete mode 100644 src/com/wentch/redkale/net/sncp/ServiceWrapper.java delete mode 100644 src/com/wentch/redkale/net/sncp/Sncp.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpCall.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpClient.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpDyn.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpDynServlet.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpFuture.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpPrepareServlet.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpRemote.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpRequest.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpResponse.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpServer.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpServlet.java delete mode 100644 src/com/wentch/redkale/net/sncp/SncpTargetAddress.java delete mode 100644 src/com/wentch/redkale/service/DataCacheListenerService.java delete mode 100644 src/com/wentch/redkale/service/DataSQLListenerService.java delete mode 100644 src/com/wentch/redkale/service/DataSourceService.java delete mode 100644 src/com/wentch/redkale/service/LocalService.java delete mode 100644 src/com/wentch/redkale/service/MultiRun.java delete mode 100644 src/com/wentch/redkale/service/RetResult.java delete mode 100644 src/com/wentch/redkale/service/Service.java delete mode 100644 src/com/wentch/redkale/service/WebSocketNodeService.java delete mode 100644 src/com/wentch/redkale/source/DataCacheListener.java delete mode 100644 src/com/wentch/redkale/source/DataCallArrayAttribute.java delete mode 100644 src/com/wentch/redkale/source/DataCallAttribute.java delete mode 100644 src/com/wentch/redkale/source/DataConnection.java delete mode 100644 src/com/wentch/redkale/source/DataDefaultSource.java delete mode 100644 src/com/wentch/redkale/source/DataSQLListener.java delete mode 100644 src/com/wentch/redkale/source/DataSource.java delete mode 100644 src/com/wentch/redkale/source/DistributeGenerator.java delete mode 100644 src/com/wentch/redkale/source/EntityCache.java delete mode 100644 src/com/wentch/redkale/source/EntityInfo.java delete mode 100644 src/com/wentch/redkale/source/FilterBean.java delete mode 100644 src/com/wentch/redkale/source/FilterColumn.java delete mode 100644 src/com/wentch/redkale/source/FilterExpress.java delete mode 100644 src/com/wentch/redkale/source/FilterGroup.java delete mode 100644 src/com/wentch/redkale/source/FilterGroups.java delete mode 100644 src/com/wentch/redkale/source/FilterJoinColumn.java delete mode 100644 src/com/wentch/redkale/source/FilterJoinNode.java delete mode 100644 src/com/wentch/redkale/source/FilterNode.java delete mode 100644 src/com/wentch/redkale/source/FilterNodeBean.java delete mode 100644 src/com/wentch/redkale/source/Flipper.java delete mode 100644 src/com/wentch/redkale/source/JDBCPoolSource.java delete mode 100644 src/com/wentch/redkale/source/Range.java delete mode 100644 src/com/wentch/redkale/source/ReckonType.java delete mode 100644 src/com/wentch/redkale/source/VirtualEntity.java delete mode 100644 src/com/wentch/redkale/util/AnyValue.java delete mode 100644 src/com/wentch/redkale/util/Attribute.java delete mode 100644 src/com/wentch/redkale/util/AutoLoad.java delete mode 100644 src/com/wentch/redkale/util/ByteArray.java delete mode 100644 src/com/wentch/redkale/util/Creator.java delete mode 100644 src/com/wentch/redkale/util/DLong.java delete mode 100644 src/com/wentch/redkale/util/DebugMethodVisitor.java delete mode 100644 src/com/wentch/redkale/util/Ignore.java delete mode 100644 src/com/wentch/redkale/util/LogLevel.java delete mode 100644 src/com/wentch/redkale/util/Nameable.java delete mode 100644 src/com/wentch/redkale/util/ObjectNode.java delete mode 100644 src/com/wentch/redkale/util/ObjectPool.java delete mode 100644 src/com/wentch/redkale/util/Reproduce.java delete mode 100644 src/com/wentch/redkale/util/ResourceFactory.java delete mode 100644 src/com/wentch/redkale/util/SelectColumn.java delete mode 100644 src/com/wentch/redkale/util/Sheet.java delete mode 100644 src/com/wentch/redkale/util/TypeToken.java delete mode 100644 src/com/wentch/redkale/util/Utility.java delete mode 100644 src/com/wentch/redkale/watch/WatchFactory.java delete mode 100644 src/com/wentch/redkale/watch/WatchNode.java delete mode 100644 src/com/wentch/redkale/watch/WatchNumber.java delete mode 100644 src/com/wentch/redkale/watch/WatchSupplier.java delete mode 100644 src/com/wentch/redkale/watch/Watchable.java diff --git a/src/com/wentch/redkale/boot/Application.java b/src/com/wentch/redkale/boot/Application.java deleted file mode 100644 index 443f6bec1..000000000 --- a/src/com/wentch/redkale/boot/Application.java +++ /dev/null @@ -1,566 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.boot; - -import com.wentch.redkale.boot.ClassFilter.FilterEntry; -import com.wentch.redkale.convert.bson.*; -import com.wentch.redkale.convert.json.*; -import com.wentch.redkale.net.*; -import com.wentch.redkale.net.sncp.*; -import com.wentch.redkale.service.*; -import com.wentch.redkale.source.*; -import com.wentch.redkale.util.*; -import com.wentch.redkale.util.AnyValue.DefaultAnyValue; -import com.wentch.redkale.watch.*; -import java.io.*; -import java.net.*; -import java.nio.*; -import java.nio.channels.*; -import java.nio.file.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import java.util.function.*; -import java.util.logging.*; -import javax.xml.parsers.*; -import org.w3c.dom.*; - -/** - * 编译时需要加入: -XDignore.symbol.file=true - *

- * 进程启动类,程序启动后读取application.xml,进行classpath扫描动态加载Service与Servlet - * 优先加载所有SNCP协议的服务, 再加载其他协议服务, - * 最后进行Service、Servlet与其他资源之间的依赖注入。 - * - * - * @author zhangjx - */ -public final class Application { - - //当前进程启动的时间, 类型: long - public static final String RESNAME_APP_TIME = "APP_TIME"; - - //当前进程的根目录, 类型:String - public static final String RESNAME_APP_HOME = "APP_HOME"; - - //application.xml 文件中resources节点的内容, 类型: AnyValue - public static final String RESNAME_APP_GRES = "APP_GRES"; - - //当前进程节点的name, 类型:String - public static final String RESNAME_APP_NODE = "APP_NODE"; - - //当前进程节点的IP地址, 类型:InetAddress、String - public static final String RESNAME_APP_ADDR = "APP_ADDR"; - - //当前SNCP Server的IP地址+端口集合 类型: Map、HashMap - public static final String RESNAME_APP_NODES = "APP_NODES"; - - //当前Service的IP地址+端口 类型: SocketAddress、InetSocketAddress、String - public static final String RESNAME_SERVER_ADDR = "SERVER_ADDR"; // SERVER_ADDR - - //当前SNCP Server所属的组 类型: String - public static final String RESNAME_SERVER_GROUP = "SERVER_GROUP"; - - //当前Service所属的组 类型: Set、String[] - public static final String RESNAME_SNCP_GROUPS = Sncp.RESNAME_SNCP_GROUPS; // SNCP_GROUPS - - protected final Map globalNodes = new HashMap<>(); - - private final Map> globalGroups = new HashMap<>(); - - protected final List transports = new ArrayList<>(); - - protected final InetAddress localAddress; - - protected final List sources = new CopyOnWriteArrayList<>(); - - protected final List servers = new CopyOnWriteArrayList<>(); - - protected CountDownLatch servicecdl; //会出现两次赋值 - - //-------------------------------------------------------------------------------------------- - private final ResourceFactory factory = ResourceFactory.root(); - - private final WatchFactory watch = WatchFactory.root(); - - private File home; - - private final Logger logger; - - private final AnyValue config; - - private final long startTime = System.currentTimeMillis(); - - private final CountDownLatch serversLatch; - - private Application(final AnyValue config) { - this.config = config; - - final File root = new File(System.getProperty(RESNAME_APP_HOME)); - this.factory.register(RESNAME_APP_TIME, long.class, this.startTime); - this.factory.register(RESNAME_APP_HOME, Path.class, root.toPath()); - this.factory.register(RESNAME_APP_HOME, File.class, root); - try { - this.factory.register(RESNAME_APP_HOME, root.getCanonicalPath()); - this.home = root.getCanonicalFile(); - } catch (IOException e) { - throw new RuntimeException(e); - } - String localaddr = config.getValue("address", "").trim(); - this.localAddress = localaddr.isEmpty() ? Utility.localInetAddress() : new InetSocketAddress(localaddr, 0).getAddress(); - Application.this.factory.register(RESNAME_APP_ADDR, Application.this.localAddress.getHostAddress()); - Application.this.factory.register(RESNAME_APP_ADDR, InetAddress.class, Application.this.localAddress); - { - String node = config.getValue("node", "").trim(); - if (node.isEmpty()) { - StringBuilder sb = new StringBuilder(); - byte[] bs = this.localAddress.getAddress(); - int v1 = bs[bs.length - 2] & 0xff; - int v2 = bs[bs.length - 1] & 0xff; - if (v1 <= 0xf) sb.append('0'); - sb.append(Integer.toHexString(v1)); - if (v2 <= 0xf) sb.append('0'); - sb.append(Integer.toHexString(v2)); - node = sb.toString(); - } - Application.this.factory.register(RESNAME_APP_NODE, node); - System.setProperty(RESNAME_APP_NODE, node); - } - //以下是初始化日志配置 - final File logconf = new File(root, "conf/logging.properties"); - if (logconf.isFile() && logconf.canRead()) { - try { - final String rootpath = root.getCanonicalPath().replace('\\', '/'); - FileInputStream fin = new FileInputStream(logconf); - Properties properties = new Properties(); - properties.load(fin); - fin.close(); - properties.entrySet().stream().forEach(x -> { - x.setValue(x.getValue().toString().replace("${APP_HOME}", rootpath)); - }); - - if (properties.getProperty("java.util.logging.FileHandler.formatter") == null) { - properties.setProperty("java.util.logging.FileHandler.formatter", LogFileHandler.LoggingFormater.class.getName()); - } - if (properties.getProperty("java.util.logging.ConsoleHandler.formatter") == null) { - properties.setProperty("java.util.logging.ConsoleHandler.formatter", LogFileHandler.LoggingFormater.class.getName()); - } - String fileHandlerPattern = properties.getProperty("java.util.logging.FileHandler.pattern"); - if (fileHandlerPattern != null && fileHandlerPattern.contains("%d")) { - final String fileHandlerClass = LogFileHandler.class.getName(); - Properties prop = new Properties(); - final String handlers = properties.getProperty("handlers"); - if (handlers != null && handlers.contains("java.util.logging.FileHandler")) { - prop.setProperty("handlers", handlers.replace("java.util.logging.FileHandler", fileHandlerClass)); - } - if (!prop.isEmpty()) { - String prefix = fileHandlerClass + "."; - properties.entrySet().stream().forEach(x -> { - if (x.getKey().toString().startsWith("java.util.logging.FileHandler.")) { - prop.put(x.getKey().toString().replace("java.util.logging.FileHandler.", prefix), x.getValue()); - } - }); - prop.entrySet().stream().forEach(x -> { - properties.put(x.getKey(), x.getValue()); - }); - } - properties.put(SncpClient.class.getSimpleName() + ".handlers", LogFileHandler.SncpLogFileHandler.class.getName()); - } - ByteArrayOutputStream out = new ByteArrayOutputStream(); - final PrintStream ps = new PrintStream(out); - properties.forEach((x, y) -> ps.println(x + "=" + y)); - LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray())); - } catch (Exception e) { - Logger.getLogger(this.getClass().getSimpleName()).log(Level.WARNING, "init logger configuration error", e); - } - } - this.logger = Logger.getLogger(this.getClass().getSimpleName()); - this.serversLatch = new CountDownLatch(config.getAnyValues("server").length + 1); - } - - public ResourceFactory getResourceFactory() { - return factory; - } - - public WatchFactory getWatchFactory() { - return watch; - } - - public File getHome() { - return home; - } - - public long getStartTime() { - return startTime; - } - - private void initLogging() { - - } - - public void init() throws Exception { - System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "" + Runtime.getRuntime().availableProcessors() * 4); - System.setProperty("convert.bson.pool.size", "128"); - System.setProperty("convert.json.pool.size", "128"); - System.setProperty("convert.bson.writer.buffer.defsize", "4096"); - System.setProperty("convert.json.writer.buffer.defsize", "4096"); - - File persist = new File(this.home, "conf/persistence.xml"); - final String homepath = this.home.getCanonicalPath(); - if (persist.isFile()) System.setProperty(DataDefaultSource.DATASOURCE_CONFPATH, persist.getCanonicalPath()); - logger.log(Level.INFO, RESNAME_APP_HOME + "=" + homepath + "\r\n" + RESNAME_APP_ADDR + "=" + this.localAddress.getHostAddress()); - String lib = config.getValue("lib", "").trim().replace("${APP_HOME}", homepath); - lib = lib.isEmpty() ? (homepath + "/conf") : (lib + ";" + homepath + "/conf"); - Server.loadLib(logger, lib); - initLogging(); - if (this.localAddress != null) { - byte[] bs = this.localAddress.getAddress(); - int v = (0xff & bs[bs.length - 2]) % 10 * 100 + (0xff & bs[bs.length - 1]); - this.factory.register("property.datasource.nodeid", "" + v); - } - //------------------------------------------------------------------------ - final AnyValue resources = config.getAnyValue("resources"); - if (resources != null) { - factory.register(RESNAME_APP_GRES, AnyValue.class, resources); - final AnyValue properties = resources.getAnyValue("properties"); - if (properties != null) { - String dfloads = properties.getValue("load"); - if (dfloads != null) { - for (String dfload : dfloads.split(";")) { - if (dfload.trim().isEmpty()) continue; - dfload = dfload.trim().replace("${APP_HOME}", home.getCanonicalPath()).replace('\\', '/'); - final File df = (dfload.indexOf('/') < 0) ? new File(home, "conf/" + dfload) : new File(dfload); - if (df.isFile()) { - Properties ps = new Properties(); - InputStream in = new FileInputStream(df); - ps.load(in); - in.close(); - ps.forEach((x, y) -> factory.register("property." + x, y)); - } - } - } - for (AnyValue prop : properties.getAnyValues("property")) { - String name = prop.getValue("name"); - String value = prop.getValue("value"); - if (name == null || value == null) continue; - if (name.startsWith("system.property.")) { - System.setProperty(name.substring("system.property.".length()), value); - } else { - factory.register("property." + name, value); - } - } - } - } - this.factory.register(BsonFactory.root()); - this.factory.register(JsonFactory.root()); - this.factory.register(BsonFactory.root().getConvert()); - this.factory.register(JsonFactory.root().getConvert()); - initResources(); - } - - private void initResources() throws Exception { - //------------------------------------------------------------------------- - final AnyValue resources = config.getAnyValue("resources"); - if (resources != null) { - //------------------------------------------------------------------------ - - for (AnyValue conf : resources.getAnyValues("group")) { - final String group = conf.getValue("name", ""); - String protocol = conf.getValue("protocol", Transport.DEFAULT_PROTOCOL).toUpperCase(); - if (!"TCP".equalsIgnoreCase(protocol) && !"UDP".equalsIgnoreCase(protocol)) { - throw new RuntimeException("Not supported Transport Protocol " + conf.getValue("protocol")); - } - Set addrs = globalGroups.get(group); - if (addrs == null) { - addrs = new LinkedHashSet<>(); - globalGroups.put(group, addrs); - } - for (AnyValue node : conf.getAnyValues("node")) { - final InetSocketAddress addr = new InetSocketAddress(node.getValue("addr"), node.getIntValue("port")); - addrs.add(addr); - String oldgroup = globalNodes.get(addr); - if (oldgroup != null) throw new RuntimeException(addr + " had one more group " + (globalNodes.get(addr))); - globalNodes.put(addr, group); - } - } - } - //------------------------------------------------------------------------ - } - - private void startSelfServer() throws Exception { - final Application application = this; - new Thread() { - { - setName("Application-Control-Thread"); - } - - @Override - public void run() { - try { - final DatagramChannel channel = DatagramChannel.open(); - channel.configureBlocking(true); - channel.socket().setSoTimeout(3000); - channel.bind(new InetSocketAddress(config.getValue("host", "127.0.0.1"), config.getIntValue("port"))); - boolean loop = true; - ByteBuffer buffer = ByteBuffer.allocateDirect(1024); - while (loop) { - buffer.clear(); - SocketAddress address = channel.receive(buffer); - buffer.flip(); - byte[] bytes = new byte[buffer.remaining()]; - buffer.get(bytes); - if ("SHUTDOWN".equalsIgnoreCase(new String(bytes))) { - try { - long s = System.currentTimeMillis(); - logger.info(application.getClass().getSimpleName() + " shutdowning"); - application.shutdown(); - buffer.clear(); - buffer.put("SHUTDOWN OK".getBytes()); - buffer.flip(); - channel.send(buffer, address); - long e = System.currentTimeMillis() - s; - logger.info(application.getClass().getSimpleName() + " shutdown in " + e + " ms"); - application.serversLatch.countDown(); - System.exit(0); - } catch (Exception ex) { - logger.log(Level.INFO, "SHUTDOWN FAIL", ex); - buffer.clear(); - buffer.put("SHUTDOWN FAIL".getBytes()); - buffer.flip(); - channel.send(buffer, address); - } - } - } - } catch (Exception e) { - logger.log(Level.INFO, "Control fail", e); - System.exit(1); - } - } - }.start(); - } - - private void sendShutDown() throws Exception { - final DatagramChannel channel = DatagramChannel.open(); - channel.configureBlocking(true); - channel.connect(new InetSocketAddress(config.getValue("host", "127.0.0.1"), config.getIntValue("port"))); - ByteBuffer buffer = ByteBuffer.allocate(128); - buffer.put("SHUTDOWN".getBytes()); - buffer.flip(); - channel.write(buffer); - buffer.clear(); - channel.configureBlocking(false); - channel.read(buffer); - buffer.flip(); - byte[] bytes = new byte[buffer.remaining()]; - buffer.get(bytes); - channel.close(); - logger.info(new String(bytes)); - Thread.sleep(500); - } - - public void start() throws Exception { - final AnyValue[] entrys = config.getAnyValues("server"); - CountDownLatch timecd = new CountDownLatch(entrys.length); - final List sncps = new ArrayList<>(); - final List others = new ArrayList<>(); - for (final AnyValue entry : entrys) { - if (entry.getValue("protocol", "").toUpperCase().startsWith("SNCP")) { - sncps.add(entry); - } else { - others.add(entry); - } - } - if (!sncps.isEmpty() && globalNodes.isEmpty()) throw new RuntimeException("found SNCP Server node but not found node info."); - - factory.register(RESNAME_APP_NODES, new TypeToken>() { - }.getType(), globalNodes); - factory.register(RESNAME_APP_NODES, new TypeToken>() { - }.getType(), globalNodes); - - factory.register(RESNAME_APP_NODES, new TypeToken>>() { - }.getType(), globalGroups); - factory.register(RESNAME_APP_NODES, new TypeToken>>() { - }.getType(), globalGroups); - - runServers(timecd, sncps); //必须确保sncp都启动后再启动其他协议 - runServers(timecd, others); - timecd.await(); - logger.info(this.getClass().getSimpleName() + " started in " + (System.currentTimeMillis() - startTime) + " ms"); - this.serversLatch.await(); - } - - @SuppressWarnings("unchecked") - private void runServers(CountDownLatch timecd, final List serconfs) throws Exception { - this.servicecdl = new CountDownLatch(serconfs.size()); - CountDownLatch sercdl = new CountDownLatch(serconfs.size()); - final AtomicBoolean inited = new AtomicBoolean(false); - final Map> nodeClasses = new HashMap<>(); - for (final AnyValue serconf : serconfs) { - Thread thread = new Thread() { - { - String host = serconf.getValue("host", "").replace("0.0.0.0", "[0]"); - setName(serconf.getValue("protocol", "Server").toUpperCase() + "-" + host + ":" + serconf.getIntValue("port") + "-Thread"); - this.setDaemon(true); - } - - @Override - public void run() { - try { - //Thread ctd = Thread.currentThread(); - //ctd.setContextClassLoader(new URLClassLoader(new URL[0], ctd.getContextClassLoader())); - final String protocol = serconf.getValue("protocol", "").replaceFirst("\\..+", "").toUpperCase(); - NodeServer server = null; - if ("SNCP".equals(protocol)) { - server = new NodeSncpServer(Application.this, serconf); - } else if ("HTTP".equals(protocol) || "HTTPS".equals(protocol)) { - server = new NodeHttpServer(Application.this, serconf); - } else { - if (!inited.get()) { - synchronized (nodeClasses) { - if (!inited.get()) { - inited.set(true); - ClassFilter profilter = new ClassFilter(NodeProtocol.class, NodeServer.class); - ClassFilter.Loader.load(home, profilter); - final Set> entrys = profilter.getFilterEntrys(); - for (FilterEntry entry : entrys) { - final Class type = entry.getType(); - NodeProtocol pros = type.getAnnotation(NodeProtocol.class); - for (String p : pros.value()) { - p = p.toUpperCase(); - if ("SNCP".equals(p) || "HTTP".equals(p) || "HTTPS".equals(p)) continue; - final Class old = nodeClasses.get(p); - if (old != null && old != type) throw new RuntimeException("Protocol(" + p + ") had NodeServer-Class(" + old.getName() + ") but repeat NodeServer-Class(" + type.getName() + ")"); - nodeClasses.put(p, type); - } - } - } - } - } - Class nodeClass = nodeClasses.get(protocol); - if (nodeClass != null) server = NodeServer.create(nodeClass, Application.this, serconf); - } - if (server == null) { - logger.log(Level.SEVERE, "Not found Server Class for protocol({0})", serconf.getValue("protocol")); - System.exit(0); - } - servers.add(server); - server.init(serconf); - server.start(); - timecd.countDown(); - sercdl.countDown(); - } catch (Exception ex) { - logger.log(Level.WARNING, serconf + " runServers error", ex); - Application.this.serversLatch.countDown(); - } - } - }; - thread.start(); - } - sercdl.await(); - } - - public static T singleton(Class serviceClass) throws Exception { - return singleton(serviceClass, false); - } - - public static T singleton(Class serviceClass, boolean remote) throws Exception { - final Application application = Application.create(); - Consumer executor = (x) -> Executors.newFixedThreadPool(8).submit(x); - T service = remote ? Sncp.createRemoteService("", executor, serviceClass, null, new LinkedHashSet<>(), null) - : Sncp.createLocalService("", executor, serviceClass, null, new LinkedHashSet<>(), null, null); - application.init(); - application.factory.register(service); - application.servicecdl = new CountDownLatch(1); - final NodeServer server = new NodeHttpServer(application, null); - server.init(application.config); - server.factory.inject(service, server); - return service; - } - - private static Application create() throws IOException { - final String home = new File(System.getProperty(RESNAME_APP_HOME, "")).getCanonicalPath(); - System.setProperty(RESNAME_APP_HOME, home); - File appfile = new File(home, "conf/application.xml"); - return new Application(load(new FileInputStream(appfile))); - } - - public static void main(String[] args) throws Exception { - //运行主程序 - final Application application = Application.create(); - if (System.getProperty("SHUTDOWN") != null) { - application.sendShutDown(); - return; - } - application.init(); - application.startSelfServer(); - try { - application.start(); - } catch (Exception e) { - application.logger.log(Level.SEVERE, "Application start error", e); - System.exit(0); - } - System.exit(0); - } - - Set findGlobalGroup(String group) { - if (group == null) return null; - Set set = globalGroups.get(group); - return set == null ? null : new LinkedHashSet<>(set); - } - - private void shutdown() throws Exception { - servers.stream().forEach((server) -> { - try { - server.shutdown(); - } catch (Exception t) { - logger.log(Level.WARNING, " shutdown server(" + server.getSocketAddress() + ") error", t); - } finally { - serversLatch.countDown(); - } - }); - for (DataSource source : sources) { - try { - source.getClass().getMethod("close").invoke(source); - } catch (Exception e) { - logger.log(Level.FINER, "close DataSource erroneous", e); - } - } - } - - private static AnyValue load(final InputStream in0) { - final DefaultAnyValue any = new DefaultAnyValue(); - try (final InputStream in = in0) { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(in); - Element root = doc.getDocumentElement(); - load(any, root); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - return any; - } - - private static void load(final DefaultAnyValue any, final Node root) { - final String home = System.getProperty(RESNAME_APP_HOME); - NamedNodeMap nodes = root.getAttributes(); - if (nodes == null) return; - for (int i = 0; i < nodes.getLength(); i++) { - Node node = nodes.item(i); - any.addValue(node.getNodeName(), node.getNodeValue().replace("${APP_HOME}", home)); - } - NodeList children = root.getChildNodes(); - if (children == null) return; - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - if (node.getNodeType() != Node.ELEMENT_NODE) continue; - DefaultAnyValue sub = new DefaultAnyValue(); - load(sub, node); - any.addValue(node.getNodeName(), sub); - } - - } -} diff --git a/src/com/wentch/redkale/boot/ClassFilter.java b/src/com/wentch/redkale/boot/ClassFilter.java deleted file mode 100644 index 6027afd7d..000000000 --- a/src/com/wentch/redkale/boot/ClassFilter.java +++ /dev/null @@ -1,436 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.boot; - -import com.wentch.redkale.util.Ignore; -import com.wentch.redkale.util.AutoLoad; -import com.wentch.redkale.util.AnyValue; -import com.wentch.redkale.util.AnyValue.DefaultAnyValue; -import java.io.*; -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.net.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.jar.*; -import java.util.logging.*; -import java.util.regex.*; - -/** - * class过滤器, 符合条件的class会保留下来存入FilterEntry。 - * - * @author zhangjx - * @param - */ -public final class ClassFilter { - - private final Set> entrys = new HashSet<>(); - - private boolean refused; - - private Class superClass; - - private Class annotationClass; - - private Pattern[] includePatterns; - - private Pattern[] excludePatterns; - - private List ors; - - private List ands; - - private AnyValue conf; - - public ClassFilter(Class annotationClass, Class superClass) { - this(annotationClass, superClass, null); - } - - public ClassFilter(Class annotationClass, Class superClass, AnyValue conf) { - this.annotationClass = annotationClass; - this.superClass = superClass; - this.conf = conf; - } - - public ClassFilter or(ClassFilter filter) { - if (ors == null) ors = new ArrayList<>(); - ors.add(filter); - return this; - } - - public ClassFilter and(ClassFilter filter) { - if (ands == null) ands = new ArrayList<>(); - ands.add(filter); - return this; - } - - /** - * 获取符合条件的class集合 - *

- * @return - */ - public final Set> getFilterEntrys() { - return entrys; - } - - /** - * 自动扫描地过滤指定的class - *

- * @param property - * @param clazzname - */ - @SuppressWarnings("unchecked") - public final void filter(AnyValue property, String clazzname) { - filter(property, clazzname, true); - } - - /** - * 过滤指定的class - *

- * @param property application.xml中对应class节点下的property属性项 - * @param clazzname class名称 - * @param autoscan 为true表示自动扫描的, false表示显著调用filter, AutoLoad的注解将被忽略 - */ - public final void filter(AnyValue property, String clazzname, boolean autoscan) { - boolean r = accept0(property, clazzname); - ClassFilter cf = r ? this : null; - if (r && ands != null) { - for (ClassFilter filter : ands) { - if (!filter.accept(property, clazzname)) return; - } - } - if (!r && ors != null) { - for (ClassFilter filter : ors) { - if (filter.accept(property, clazzname)) { - cf = filter; - break; - } - } - } - if (cf == null) return; - try { - Class clazz = Class.forName(clazzname); - if (!cf.accept(property, clazz, autoscan)) return; - if (cf.conf != null) { - if (property == null) { - property = cf.conf; - } else { - if (property instanceof DefaultAnyValue) { - ((DefaultAnyValue) property).addAll(cf.conf); - } else { - DefaultAnyValue dav = new DefaultAnyValue(); - dav.addAll(property); - dav.addAll(cf.conf); - property = dav; - } - } - } - entrys.add(new FilterEntry(clazz, autoscan, property)); - } catch (Throwable cfe) { - } - } - - private static Pattern[] toPattern(String[] regs) { - if (regs == null) return null; - int i = 0; - Pattern[] rs = new Pattern[regs.length]; - for (String reg : regs) { - if (reg == null || reg.trim().isEmpty()) continue; - rs[i++] = Pattern.compile(reg.trim()); - } - if (i == 0) return null; - if (i == rs.length) return rs; - Pattern[] ps = new Pattern[i]; - System.arraycopy(rs, 0, ps, 0, i); - return ps; - } - - /** - * 判断class是否有效 - *

- * @param property - * @param classname - * @return - */ - public boolean accept(AnyValue property, String classname) { - boolean r = accept0(property, classname); - if (r && ands != null) { - for (ClassFilter filter : ands) { - if (!filter.accept(property, classname)) return false; - } - } - if (!r && ors != null) { - for (ClassFilter filter : ors) { - if (filter.accept(property, classname)) return true; - } - } - return r; - } - - private boolean accept0(AnyValue property, String classname) { - if (this.refused) return false; - if (classname.startsWith("java.") || classname.startsWith("javax.")) return false; - if (excludePatterns != null) { - for (Pattern reg : excludePatterns) { - if (reg.matcher(classname).matches()) return false; - } - } - if (includePatterns != null) { - for (Pattern reg : includePatterns) { - if (reg.matcher(classname).matches()) return true; - } - } - return includePatterns == null; - } - - /** - * 判断class是否有效 - *

- * @param property - * @param clazz - * @param autoscan - * @return - */ - @SuppressWarnings("unchecked") - public boolean accept(AnyValue property, Class clazz, boolean autoscan) { - if (this.refused || !Modifier.isPublic(clazz.getModifiers())) return false; - if (clazz.getAnnotation(Ignore.class) != null) return false; - if (autoscan) { - AutoLoad auto = (AutoLoad) clazz.getAnnotation(AutoLoad.class); - if (auto != null && !auto.value()) return false; - } - if (annotationClass != null && clazz.getAnnotation(annotationClass) == null) return false; - return superClass == null || (clazz != superClass && superClass.isAssignableFrom(clazz)); - } - - public void setSuperClass(Class superClass) { - this.superClass = superClass; - } - - public void setAnnotationClass(Class annotationClass) { - this.annotationClass = annotationClass; - } - - public Pattern[] getIncludePatterns() { - return includePatterns; - } - - public void setIncludePatterns(String[] includePatterns) { - this.includePatterns = toPattern(includePatterns); - } - - public Pattern[] getExcludePatterns() { - return excludePatterns; - } - - public void setExcludePatterns(String[] excludePatterns) { - this.excludePatterns = toPattern(excludePatterns); - } - - public Class getAnnotationClass() { - return annotationClass; - } - - public Class getSuperClass() { - return superClass; - } - - public boolean isRefused() { - return refused; - } - - public void setRefused(boolean refused) { - this.refused = refused; - } - - /** - * 存放符合条件的class与class指定的属性项 - *

- * @param - */ - public static final class FilterEntry { - - private final HashSet groups = new LinkedHashSet<>(); - - private final String name; - - private final Class type; - - private final AnyValue property; - - private final boolean autoload; - - public FilterEntry(Class type, AnyValue property) { - this(type, false, property); - } - - public FilterEntry(Class type, final boolean autoload, AnyValue property) { - this.type = type; - String str = property == null ? null : property.getValue("groups"); - if (str != null) groups.addAll(Arrays.asList(str.split(";"))); - this.property = property; - this.autoload = autoload; - this.name = property == null ? "" : property.getValue("name", ""); - } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "[thread=" + Thread.currentThread().getName() - + ", type=" + this.type.getSimpleName() + ", name=" + name + ", groups=" + groups + "]"; - } - - @Override - public int hashCode() { - return this.type.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - return (this.type == ((FilterEntry) obj).type && this.groups.equals(((FilterEntry) obj).groups) && this.name.equals(((FilterEntry) obj).name)); - } - - public Class getType() { - return type; - } - - public String getName() { - return name; - } - - public AnyValue getProperty() { - return property; - } - - public HashSet getGroups() { - return groups; - } - - public boolean isAutoload() { - return autoload; - } - - } - - /** - * class加载类 - */ - public static class Loader { - - protected static final Logger logger = Logger.getLogger(Loader.class.getName()); - - protected static final ConcurrentMap> cache = new ConcurrentHashMap<>(); - - public static void close() { - cache.clear(); - } - - /** - * 加载当前线程的classpath扫描所有class进行过滤 - *

- * @param exclude 不需要扫描的文件夹, 可以为null - * @param filters - * @throws IOException - */ - public static void load(final File exclude, final ClassFilter... filters) throws IOException { - URLClassLoader loader = (URLClassLoader) Thread.currentThread().getContextClassLoader(); - List urlfiles = new ArrayList<>(2); - List urljares = new ArrayList<>(2); - final URL exurl = exclude != null ? exclude.toURI().toURL() : null; - for (URL url : loader.getURLs()) { - if (exurl != null && exurl.sameFile(url)) continue; - if (url.getPath().endsWith(".jar")) { - urljares.add(url); - } else { - urlfiles.add(url); - } - } - - List files = new ArrayList<>(); - boolean debug = logger.isLoggable(Level.FINEST); - StringBuilder debugstr = new StringBuilder(); - for (final URL url : urljares) { - Set classes = cache.get(url); - if (classes == null) { - synchronized (cache) { - if (cache.get(url) == null) { - classes = new CopyOnWriteArraySet<>(); - cache.put(url, classes); - } else { - classes = cache.get(url); - } - } - try (JarFile jar = new JarFile(URLDecoder.decode(url.getFile(), "UTF-8"))) { - Enumeration it = jar.entries(); - while (it.hasMoreElements()) { - String entryname = it.nextElement().getName().replace('/', '.'); - if (entryname.endsWith(".class") && entryname.indexOf('$') < 0) { - String classname = entryname.substring(0, entryname.length() - 6); - if (classname.startsWith("javax.") || classname.startsWith("com.sun.") || classname.startsWith("com.mysql.")) continue; - classes.add(classname); - if (debug) debugstr.append(classname).append("\r\n"); - for (final ClassFilter filter : filters) { - if (filter != null) filter.filter(null, classname); - } - } - } - } - } else { - for (String classname : classes) { - for (final ClassFilter filter : filters) { - if (filter != null) filter.filter(null, classname); - } - } - } - } - for (final URL url : urlfiles) { - Set classes = cache.get(url); - if (classes == null) { - synchronized (cache) { - if (cache.get(url) == null) { - classes = new CopyOnWriteArraySet<>(); - cache.put(url, classes); - } else { - classes = cache.get(url); - } - } - files.clear(); - File root = new File(url.getFile()); - String rootpath = root.getPath(); - loadClassFiles(exclude, root, files); - for (File f : files) { - String classname = f.getPath().substring(rootpath.length() + 1, f.getPath().length() - 6).replace(File.separatorChar, '.'); - if (classname.startsWith("javax.") || classname.startsWith("org.") || classname.startsWith("com.mysql.")) continue; - classes.add(classname); - if (debug) debugstr.append(classname).append("\r\n"); - for (final ClassFilter filter : filters) { - if (filter != null) filter.filter(null, classname); - } - } - } else { - for (String classname : classes) { - for (final ClassFilter filter : filters) { - if (filter != null) filter.filter(null, classname); - } - } - } - } - //if (debug) logger.log(Level.INFO, "scan classes: \r\n{0}", debugstr); - } - - private static void loadClassFiles(File exclude, File root, List files) { - if (root.isFile() && root.getName().endsWith(".class")) { - files.add(root); - } else if (root.isDirectory()) { - if (exclude != null && exclude.equals(root)) return; - for (File f : root.listFiles()) { - loadClassFiles(exclude, f, files); - } - } - } - } -} diff --git a/src/com/wentch/redkale/boot/LogFileHandler.java b/src/com/wentch/redkale/boot/LogFileHandler.java deleted file mode 100644 index 0c16f8977..000000000 --- a/src/com/wentch/redkale/boot/LogFileHandler.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.boot; - -import java.io.*; -import java.nio.file.*; -import static java.nio.file.StandardCopyOption.*; -import java.time.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import java.util.logging.*; -import java.util.logging.Formatter; - -/** - * 自定义的日志存储类 - *

- * @author zhangjx - */ -public class LogFileHandler extends Handler { - - public static class SncpLogFileHandler extends LogFileHandler { - - @Override - public String getPrefix() { - return "sncp-"; - } - } - - public static class LoggingFormater extends Formatter { - - private static final String format = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL %4$s %2$s\r\n%5$s%6$s\r\n"; - - @Override - public String format(LogRecord record) { - String source; - if (record.getSourceClassName() != null) { - source = record.getSourceClassName(); - if (record.getSourceMethodName() != null) { - source += " " + record.getSourceMethodName(); - } - } else { - source = record.getLoggerName(); - } - String message = formatMessage(record); - String throwable = ""; - if (record.getThrown() != null) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw) { - @Override - public void println() { - super.print("\r\n"); - } - }; - pw.println(); - record.getThrown().printStackTrace(pw); - pw.close(); - throwable = sw.toString(); - } - return String.format(format, - System.currentTimeMillis(), - source, - record.getLoggerName(), - record.getLevel().getName(), - message, - throwable); - } - - } - - protected final LinkedBlockingQueue records = new LinkedBlockingQueue(); - - private String pattern; - - private int limit; //文件大小限制 - - private final AtomicInteger index = new AtomicInteger(); - - private int count = 1; //文件限制 - - private long tomorrow; - - private boolean append; - - private final AtomicLong length = new AtomicLong(); - - private File logfile; - - private OutputStream stream; - - public LogFileHandler() { - updateTomorrow(); - configure(); - open(); - } - - private void updateTomorrow() { - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - cal.add(Calendar.DAY_OF_YEAR, 1); - long t = cal.getTimeInMillis(); - if (this.tomorrow != t) index.set(0); - this.tomorrow = t; - } - - private void open() { - final String name = "Logging-" + getClass().getSimpleName() + "-Thread"; - new Thread() { - { - setName(name); - setDaemon(true); - } - - @Override - public void run() { - while (true) { - try { - LogRecord record = records.take(); - final boolean bigger = (limit > 0 && limit <= length.get()); - if (bigger || tomorrow <= record.getMillis()) { - updateTomorrow(); - if (stream != null) { - stream.close(); - if (bigger) { - for (int i = Math.min(count - 2, index.get() - 1); i > 0; i--) { - File greater = new File(logfile.getPath() + "." + i); - if (greater.exists()) Files.move(greater.toPath(), new File(logfile.getPath() + "." + (i + 1)).toPath(), REPLACE_EXISTING, ATOMIC_MOVE); - } - Files.move(logfile.toPath(), new File(logfile.getPath() + ".1").toPath(), REPLACE_EXISTING, ATOMIC_MOVE); - } - stream = null; - } - } - if (stream == null) { - index.incrementAndGet(); - java.time.LocalDate date = LocalDate.now(); - logfile = new File(pattern.replace("%m", String.valueOf((date.getYear() * 100 + date.getMonthValue()))).replace("%d", String.valueOf((date.getYear() * 10000 + date.getMonthValue() * 100 + date.getDayOfMonth())))); - logfile.getParentFile().mkdirs(); - length.set(logfile.length()); - stream = new FileOutputStream(logfile, append); - } - //----------------------写日志------------------------- - String message = getFormatter().format(record); - String encoding = getEncoding(); - byte[] bytes = encoding == null ? message.getBytes() : message.getBytes(encoding); - stream.write(bytes); - length.addAndGet(bytes.length); - } catch (Exception e) { - ErrorManager err = getErrorManager(); - if (err != null) err.error(null, e, ErrorManager.WRITE_FAILURE); - } - } - - } - }.start(); - } - - public String getPrefix() { - return ""; - } - - private void configure() { - LogManager manager = LogManager.getLogManager(); - String cname = LogFileHandler.class.getName(); - pattern = manager.getProperty(cname + ".pattern"); - if (pattern == null) { - pattern = "logs-%m/" + getPrefix() + "log-%d.log"; - } else { - int pos = pattern.lastIndexOf('/'); - if (pos > 0) { - pattern = pattern.substring(0, pos + 1) + getPrefix() + pattern.substring(pos + 1); - } else { - pattern = getPrefix() + pattern; - } - } - String limitstr = manager.getProperty(cname + ".limit"); - try { - if (limitstr != null) limit = Math.abs(Integer.decode(limitstr)); - } catch (Exception e) { - } - String countstr = manager.getProperty(cname + ".count"); - try { - if (countstr != null) count = Math.max(1, Math.abs(Integer.decode(countstr))); - } catch (Exception e) { - } - String appendstr = manager.getProperty(cname + ".append"); - try { - if (appendstr != null) append = "true".equalsIgnoreCase(appendstr) || "1".equals(appendstr); - } catch (Exception e) { - } - String levelstr = manager.getProperty(cname + ".level"); - try { - if (levelstr != null) { - Level l = Level.parse(levelstr); - setLevel(l != null ? l : Level.ALL); - } - } catch (Exception e) { - } - String filterstr = manager.getProperty(cname + ".filter"); - try { - if (filterstr != null) { - Class clz = ClassLoader.getSystemClassLoader().loadClass(filterstr); - setFilter((Filter) clz.newInstance()); - } - } catch (Exception e) { - } - String formatterstr = manager.getProperty(cname + ".formatter"); - try { - if (formatterstr != null) { - Class clz = ClassLoader.getSystemClassLoader().loadClass(formatterstr); - setFormatter((Formatter) clz.newInstance()); - } - } catch (Exception e) { - } - if (getFormatter() == null) setFormatter(new SimpleFormatter()); - - String encodingstr = manager.getProperty(cname + ".encoding"); - try { - if (encodingstr != null) setEncoding(encodingstr); - } catch (Exception e) { - } - } - - @Override - public void publish(LogRecord record) { - final String sourceClassName = record.getSourceClassName(); - if (sourceClassName == null || true) { - StackTraceElement[] ses = new Throwable().getStackTrace(); - for (int i = 2; i < ses.length; i++) { - if (ses[i].getClassName().startsWith("java.util.logging")) continue; - record.setSourceClassName('[' + Thread.currentThread().getName() + "] " + ses[i].getClassName()); - record.setSourceMethodName(ses[i].getMethodName()); - break; - } - } else { - record.setSourceClassName('[' + Thread.currentThread().getName() + "] " + sourceClassName); - } - records.offer(record); - } - - @Override - public void flush() { - try { - if (stream != null) stream.flush(); - } catch (Exception e) { - ErrorManager err = getErrorManager(); - if (err != null) err.error(null, e, ErrorManager.FLUSH_FAILURE); - } - } - - @Override - public void close() throws SecurityException { - try { - if (stream != null) stream.close(); - } catch (Exception e) { - ErrorManager err = getErrorManager(); - if (err != null) err.error(null, e, ErrorManager.CLOSE_FAILURE); - } - } - -} diff --git a/src/com/wentch/redkale/boot/NodeHttpServer.java b/src/com/wentch/redkale/boot/NodeHttpServer.java deleted file mode 100644 index 81607dc38..000000000 --- a/src/com/wentch/redkale/boot/NodeHttpServer.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.boot; - -import com.wentch.redkale.net.http.WebServlet; -import com.wentch.redkale.net.http.HttpServer; -import com.wentch.redkale.net.http.HttpServlet; -import com.wentch.redkale.util.AnyValue; -import com.wentch.redkale.boot.ClassFilter.FilterEntry; -import com.wentch.redkale.net.*; -import com.wentch.redkale.net.http.*; -import com.wentch.redkale.net.sncp.*; -import com.wentch.redkale.service.*; -import com.wentch.redkale.util.*; -import com.wentch.redkale.util.AnyValue.DefaultAnyValue; -import java.lang.reflect.*; -import java.net.InetSocketAddress; -import java.util.*; -import java.util.logging.*; -import javax.annotation.*; - -/** - * HTTP Server节点的配置Server - * - * @author zhangjx - */ -@NodeProtocol({"HTTP", "HTTPS"}) -public final class NodeHttpServer extends NodeServer { - - private final HttpServer httpServer; - - public NodeHttpServer(Application application, AnyValue serconf) { - super(application, application.getResourceFactory().createChild(), createServer(application, serconf)); - this.httpServer = (HttpServer) server; - } - - private static Server createServer(Application application, AnyValue serconf) { - return new HttpServer(application.getStartTime(), application.getWatchFactory()); - } - - @Override - public InetSocketAddress getSocketAddress() { - return httpServer == null ? null : httpServer.getSocketAddress(); - } - - @Override - protected ClassFilter createServletClassFilter() { - return createClassFilter(null, WebServlet.class, HttpServlet.class, null, "servlets", "servlet"); - } - - @Override - protected void loadServlet(ClassFilter servletFilter) throws Exception { - if (httpServer != null) loadHttpServlet(this.nodeConf.getAnyValue("servlets"), servletFilter); - } - - @Override - protected void loadService(ClassFilter serviceFilter) throws Exception { - super.loadService(serviceFilter); - initWebSocketService(); - } - - private void initWebSocketService() { - final NodeServer self = this; - final ResourceFactory regFactory = application.getResourceFactory(); - factory.add(WebSocketNode.class, (ResourceFactory rf, final Object src, Field field, Object attachment) -> { - try { - Resource rs = field.getAnnotation(Resource.class); - if (rs == null) return; - if (!(src instanceof WebSocketServlet)) return; - String rcname = rs.name(); - if (rcname.equals(ResourceFactory.RESOURCE_PARENT_NAME)) rcname = ((WebSocketServlet) src).name(); - synchronized (regFactory) { - Service nodeService = (Service) rf.find(rcname, WebSocketNode.class); - if (nodeService == null) { - nodeService = Sncp.createLocalService(rcname, getExecutor(), (Class) WebSocketNodeService.class, - getSncpAddress(), sncpDefaultGroups, sncpSameGroupTransports, sncpDiffGroupTransports); - regFactory.register(rcname, WebSocketNode.class, nodeService); - factory.inject(nodeService, self); - logger.fine("[" + Thread.currentThread().getName() + "] Load " + nodeService); - if (getSncpAddress() != null) { - NodeSncpServer sncpServer = null; - for (NodeServer node : application.servers) { - if (node.isSNCP() && getSncpAddress().equals(node.getSncpAddress())) { - sncpServer = (NodeSncpServer) node; - } - } - ServiceWrapper wrapper = new ServiceWrapper(WebSocketNodeService.class, nodeService, rcname, getSncpGroup(), sncpDefaultGroups, null); - sncpServer.getSncpServer().addService(wrapper); - } - } - field.set(src, nodeService); - } - } catch (Exception e) { - logger.log(Level.SEVERE, "WebSocketNode inject error", e); - } - }); - } - - protected void loadHttpServlet(final AnyValue conf, final ClassFilter filter) throws Exception { - final StringBuilder sb = logger.isLoggable(Level.FINE) ? new StringBuilder() : null; - final String prefix = conf == null ? "" : conf.getValue("prefix", ""); - final String threadName = "[" + Thread.currentThread().getName() + "] "; - for (FilterEntry en : filter.getFilterEntrys()) { - Class clazz = (Class) en.getType(); - if (Modifier.isAbstract(clazz.getModifiers())) continue; - WebServlet ws = clazz.getAnnotation(WebServlet.class); - if (ws == null || ws.value().length == 0) continue; - final HttpServlet servlet = clazz.newInstance(); - factory.inject(servlet, this); - String[] mappings = ws.value(); - if (ws.fillurl() && !prefix.isEmpty()) { - for (int i = 0; i < mappings.length; i++) { - mappings[i] = prefix + mappings[i]; - } - } - DefaultAnyValue servletConf = (DefaultAnyValue) en.getProperty(); - WebInitParam[] webparams = ws.initParams(); - if (webparams.length > 0) { - if (servletConf == null) servletConf = new DefaultAnyValue(); - for (WebInitParam webparam : webparams) { - servletConf.addValue(webparam.name(), webparam.value()); - } - } - this.httpServer.addHttpServlet(servlet, servletConf, mappings); - if (sb != null) sb.append(threadName).append(" Loaded ").append(clazz.getName()).append(" --> ").append(Arrays.toString(mappings)).append(LINE_SEPARATOR); - } - if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString()); - } - -} diff --git a/src/com/wentch/redkale/boot/NodeProtocol.java b/src/com/wentch/redkale/boot/NodeProtocol.java deleted file mode 100644 index d1e9d9efd..000000000 --- a/src/com/wentch/redkale/boot/NodeProtocol.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.boot; - -import java.lang.annotation.*; - -/** - * - * @author zhangjx - */ -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface NodeProtocol { - String[] value(); -} diff --git a/src/com/wentch/redkale/boot/NodeServer.java b/src/com/wentch/redkale/boot/NodeServer.java deleted file mode 100644 index 78f9fefa9..000000000 --- a/src/com/wentch/redkale/boot/NodeServer.java +++ /dev/null @@ -1,442 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.boot; - -import static com.wentch.redkale.boot.Application.*; -import com.wentch.redkale.boot.ClassFilter.FilterEntry; -import com.wentch.redkale.net.sncp.ServiceWrapper; -import com.wentch.redkale.net.Server; -import com.wentch.redkale.net.sncp.Sncp; -import com.wentch.redkale.service.Service; -import com.wentch.redkale.util.AnyValue; -import com.wentch.redkale.net.*; -import com.wentch.redkale.net.http.*; -import com.wentch.redkale.service.*; -import com.wentch.redkale.source.*; -import com.wentch.redkale.util.*; -import com.wentch.redkale.util.AnyValue.DefaultAnyValue; -import java.io.*; -import java.lang.annotation.Annotation; -import java.lang.reflect.*; -import java.net.*; -import java.util.*; -import java.util.function.Consumer; -import java.util.logging.*; -import javax.annotation.*; - -/** - * - * @author zhangjx - */ -public abstract class NodeServer { - - public static final String LINE_SEPARATOR = "\r\n"; - - protected final Logger logger; - - protected final boolean fine; - - protected final Application application; - - protected final ResourceFactory factory; - - protected final Server server; - - private String sncpGroup = null; //当前Server的SNCP协议的组 - - private String nodeProtocol = Transport.DEFAULT_PROTOCOL; - - private InetSocketAddress sncpAddress; //HttpServer中的sncpAddress 为所属group对应的SncpServer, 为null表示只是单节点,没有分布式结构 - - protected Consumer consumer; - - protected AnyValue nodeConf; - - protected final HashSet sncpDefaultGroups = new LinkedHashSet<>(); - - protected final List sncpSameGroupTransports = new ArrayList<>(); - - protected final List sncpDiffGroupTransports = new ArrayList<>(); - - protected final Set localServiceWrappers = new LinkedHashSet<>(); - - protected final Set remoteServiceWrappers = new LinkedHashSet<>(); - - public NodeServer(Application application, ResourceFactory factory, Server server) { - this.application = application; - this.factory = factory; - this.server = server; - this.logger = Logger.getLogger(this.getClass().getSimpleName()); - this.fine = logger.isLoggable(Level.FINE); - } - - protected Consumer getExecutor() throws Exception { - if (server == null) return null; - final Field field = Server.class.getDeclaredField("context"); - field.setAccessible(true); - return new Consumer() { - - private Context context; - - @Override - public void accept(Runnable t) { - if (context == null && server != null) { - try { - this.context = (Context) field.get(server); - } catch (Exception e) { - logger.log(Level.SEVERE, "Server (" + server.getSocketAddress() + ") cannot find Context", e); - } - } - context.submit(t); - } - - }; - } - - public static NodeServer create(Class clazz, Application application, AnyValue serconf) { - try { - return clazz.getConstructor(Application.class, AnyValue.class).newInstance(application, serconf); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public void init(AnyValue config) throws Exception { - this.nodeConf = config == null ? AnyValue.create() : config; - if (isSNCP()) { // SNCP协议 - String host = this.nodeConf.getValue("host", "0.0.0.0").replace("0.0.0.0", ""); - this.sncpAddress = new InetSocketAddress(host.isEmpty() ? application.localAddress.getHostAddress() : host, this.nodeConf.getIntValue("port")); - this.sncpGroup = application.globalNodes.get(this.sncpAddress); - if (this.sncpGroup == null) throw new RuntimeException("Server (" + String.valueOf(config).replaceAll("\\s+", " ") + ") not found info"); - if (server != null) this.nodeProtocol = server.getProtocol(); - } - initGroup(); - if (this.sncpAddress != null) this.factory.register(RESNAME_SERVER_ADDR, this.sncpAddress); - if (this.sncpGroup != null) this.factory.register(RESNAME_SERVER_GROUP, this.sncpGroup); - { - //设置root文件夹 - String webroot = config.getValue("root", "root"); - File myroot = new File(webroot); - if (!webroot.contains(":") && !webroot.startsWith("/")) { - myroot = new File(System.getProperty(Application.RESNAME_APP_HOME), webroot); - } - final String homepath = myroot.getCanonicalPath(); - Server.loadLib(logger, config.getValue("lib", "") + ";" + homepath + "/lib/*;" + homepath + "/classes"); - if (server != null) server.init(config); - } - initResource(); - //prepare(); - ClassFilter servletFilter = createServletClassFilter(); - ClassFilter serviceFilter = createServiceClassFilter(); - long s = System.currentTimeMillis(); - if (servletFilter == null) { - ClassFilter.Loader.load(application.getHome(), serviceFilter); - } else { - ClassFilter.Loader.load(application.getHome(), serviceFilter, servletFilter); - } - long e = System.currentTimeMillis() - s; - logger.info(this.getClass().getSimpleName() + " load filter class in " + e + " ms"); - loadService(serviceFilter); //必须在servlet之前 - loadServlet(servletFilter); - } - - protected abstract void loadServlet(ClassFilter servletFilter) throws Exception; - - private void initResource() { - final NodeServer self = this; - //--------------------------------------------------------------------------------------------- - final ResourceFactory regFactory = application.getResourceFactory(); - factory.add(DataSource.class, (ResourceFactory rf, final Object src, Field field, final Object attachment) -> { - try { - Resource rs = field.getAnnotation(Resource.class); - if (rs == null) return; - if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; - DataSource source = new DataDefaultSource(rs.name()); - application.sources.add(source); - regFactory.register(rs.name(), DataSource.class, source); - List sameGroupTransports = sncpSameGroupTransports; - List diffGroupTransports = sncpDiffGroupTransports; - try { - Field ts = src.getClass().getDeclaredField("_sameGroupTransports"); - ts.setAccessible(true); - Transport[] lts = (Transport[]) ts.get(src); - sameGroupTransports = Arrays.asList(lts); - - ts = src.getClass().getDeclaredField("_diffGroupTransports"); - ts.setAccessible(true); - lts = (Transport[]) ts.get(src); - diffGroupTransports = Arrays.asList(lts); - } catch (Exception e) { - //src 不含 MultiRun 方法 - } - if (factory.find(rs.name(), DataCacheListener.class) == null) { - Service cacheListenerService = Sncp.createLocalService(rs.name(), getExecutor(), DataCacheListenerService.class, this.sncpAddress, sncpDefaultGroups, sameGroupTransports, diffGroupTransports); - regFactory.register(rs.name(), DataCacheListener.class, cacheListenerService); - ServiceWrapper wrapper = new ServiceWrapper(DataCacheListenerService.class, cacheListenerService, rs.name(), sncpGroup, sncpDefaultGroups, null); - localServiceWrappers.add(wrapper); - if (consumer != null) consumer.accept(wrapper); - rf.inject(cacheListenerService, self); - } - field.set(src, source); - rf.inject(source, self); // 给 "datasource.nodeid" 赋值 - } catch (Exception e) { - logger.log(Level.SEVERE, "DataSource inject error", e); - } - }); - } - - private void initGroup() { - final AnyValue[] services = this.nodeConf.getAnyValues("services"); - final String[] groups = services.length < 1 ? new String[]{""} : services[0].getValue("groups", "").split(";"); - this.sncpDefaultGroups.addAll(Arrays.asList(groups)); - if (!isSNCP()) { - NodeSncpServer sncpServer = null; - for (NodeServer node : application.servers) { - if (!node.isSNCP()) continue; - if (!this.sncpDefaultGroups.contains(node.sncpGroup)) continue; - sncpServer = (NodeSncpServer) node; - break; - } - if (sncpServer == null && (groups.length == 1 && groups[0].isEmpty())) { - for (NodeServer node : application.servers) { - if (!node.isSNCP()) continue; - sncpServer = (NodeSncpServer) node; - break; - } - } - if (sncpServer != null) { - this.sncpAddress = sncpServer.getSncpAddress(); - this.sncpGroup = sncpServer.getSncpGroup(); - this.sncpDefaultGroups.clear(); - this.sncpDefaultGroups.addAll(sncpServer.sncpDefaultGroups); - this.sncpSameGroupTransports.addAll(sncpServer.sncpSameGroupTransports); - this.sncpDiffGroupTransports.addAll(sncpServer.sncpDiffGroupTransports); - return; - } - } - final Set sameGroupAddrs = application.findGlobalGroup(this.sncpGroup); - final Map> diffGroupAddrs = new HashMap<>(); - for (String groupitem : groups) { - final Set addrs = application.findGlobalGroup(groupitem); - if (addrs == null || groupitem.equals(this.sncpGroup)) continue; - diffGroupAddrs.put(groupitem, addrs); - } - if (sameGroupAddrs != null) { - sameGroupAddrs.remove(this.sncpAddress); - for (InetSocketAddress iaddr : sameGroupAddrs) { - sncpSameGroupTransports.add(loadTransport(this.sncpGroup, getNodeProtocol(), iaddr)); - } - } - diffGroupAddrs.forEach((k, v) -> sncpDiffGroupTransports.add(loadTransport(k, getNodeProtocol(), v))); - } - - @SuppressWarnings("unchecked") - protected void loadService(ClassFilter serviceFilter) throws Exception { - if (serviceFilter == null) return; - final String threadName = "[" + Thread.currentThread().getName() + "] "; - final Set> entrys = serviceFilter.getFilterEntrys(); - ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : factory; - final Set sg = application.findGlobalGroup(this.sncpGroup); - for (FilterEntry entry : entrys) { //service实现类 - final Class type = entry.getType(); - if (type.isInterface()) continue; - if (Modifier.isFinal(type.getModifiers())) continue; - if (!Modifier.isPublic(type.getModifiers())) continue; - if (Modifier.isAbstract(type.getModifiers())) continue; - if (type.getAnnotation(Ignore.class) != null) continue; - if (!isSNCP() && factory.find(entry.getName(), type) != null) continue; - final Set sameGroupAddrs = new LinkedHashSet<>(); - final Map> diffGroupAddrs = new HashMap<>(); - final HashSet groups = entry.getGroups(); - for (String g : groups) { - if (g.isEmpty()) continue; - if (g.equals(this.sncpGroup) && sg != null) sameGroupAddrs.addAll(sg); - Set set = application.findGlobalGroup(g); - if (set == null) throw new RuntimeException(type.getName() + " has illegal group (" + groups + ")"); - if (!g.equals(this.sncpGroup)) { - diffGroupAddrs.put(g, set); - } - } - List diffGroupTransports = new ArrayList<>(); - diffGroupAddrs.forEach((k, v) -> diffGroupTransports.add(loadTransport(k, server.getProtocol(), v))); - - ServiceWrapper wrapper; - if ((sameGroupAddrs.isEmpty() && diffGroupAddrs.isEmpty()) || sameGroupAddrs.contains(this.sncpAddress) || type.getAnnotation(LocalService.class) != null) { //本地模式 - sameGroupAddrs.remove(this.sncpAddress); - List sameGroupTransports = new ArrayList<>(); - for (InetSocketAddress iaddr : sameGroupAddrs) { - Set tset = new HashSet<>(); - tset.add(iaddr); - sameGroupTransports.add(loadTransport(this.sncpGroup, server.getProtocol(), tset)); - } - Service service = Sncp.createLocalService(entry.getName(), getExecutor(), type, this.sncpAddress, groups, sameGroupTransports, diffGroupTransports); - wrapper = new ServiceWrapper(type, service, this.sncpGroup, entry); - if (fine) logger.fine("[" + Thread.currentThread().getName() + "] " + service + " loaded"); - } else { - sameGroupAddrs.remove(this.sncpAddress); - StringBuilder g = new StringBuilder(); - diffGroupAddrs.forEach((k, v) -> { - if (g.length() > 0) g.append(';'); - g.append(k); - sameGroupAddrs.addAll(v); - }); - if (sameGroupAddrs.isEmpty()) throw new RuntimeException(type.getName() + " has no remote address on group (" + groups + ")"); - Service service = Sncp.createRemoteService(entry.getName(), getExecutor(), type, this.sncpAddress, groups, loadTransport(g.toString(), server.getProtocol(), sameGroupAddrs)); - wrapper = new ServiceWrapper(type, service, "", entry); - if (fine) logger.fine("[" + Thread.currentThread().getName() + "] " + service + " loaded"); - } - if (factory.find(wrapper.getName(), wrapper.getType()) == null) { - regFactory.register(wrapper.getName(), wrapper.getType(), wrapper.getService()); - if (wrapper.getService() instanceof DataSource) { - regFactory.register(wrapper.getName(), DataSource.class, wrapper.getService()); - } else if (wrapper.getService() instanceof DataCacheListener) { - regFactory.register(wrapper.getName(), DataCacheListener.class, wrapper.getService()); - } else if (wrapper.getService() instanceof DataSQLListener) { - regFactory.register(wrapper.getName(), DataSQLListener.class, wrapper.getService()); - } else if (wrapper.getService() instanceof WebSocketNode) { - regFactory.register(wrapper.getName(), WebSocketNode.class, wrapper.getService()); - } - if (wrapper.isRemote()) { - remoteServiceWrappers.add(wrapper); - } else { - localServiceWrappers.add(wrapper); - if (consumer != null) consumer.accept(wrapper); - } - } else if (isSNCP() && !entry.isAutoload()) { - throw new RuntimeException(ServiceWrapper.class.getSimpleName() + "(class:" + type.getName() + ", name:" + entry.getName() + ", group:" + groups + ") is repeat."); - } - } - application.servicecdl.countDown(); - application.servicecdl.await(); - - final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null; - //---------------- inject ---------------- - new HashSet<>(localServiceWrappers).forEach(y -> { - factory.inject(y.getService(), NodeServer.this); - }); - remoteServiceWrappers.forEach(y -> { - factory.inject(y.getService(), NodeServer.this); - if (sb != null) { - sb.append(threadName).append("RemoteService(").append(y.getType()).append(':').append(y.getName()).append(") loaded").append(LINE_SEPARATOR); - } - }); - //----------------- init ----------------- - localServiceWrappers.parallelStream().forEach(y -> { - long s = System.currentTimeMillis(); - y.getService().init(y.getConf()); - long e = System.currentTimeMillis() - s; - if (e > 2 && sb != null) { - sb.append(threadName).append("LocalService(").append(y.getType()).append(':').append(y.getName()).append(") init ").append(e).append("ms").append(LINE_SEPARATOR); - } - }); - if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString()); - } - - protected Transport loadTransport(String group, String protocol, InetSocketAddress addr) { - if (addr == null) return null; - Set set = new HashSet<>(); - set.add(addr); - return loadTransport(group, protocol, set); - } - - protected Transport loadTransport(String group, String protocol, Set addrs) { - Transport transport = null; - if (!addrs.isEmpty()) { - synchronized (application.transports) { - for (Transport tran : application.transports) { - if (tran.match(addrs)) { - transport = tran; - break; - } - } - if (transport == null) { - transport = new Transport(group + "_" + application.transports.size(), protocol, application.getWatchFactory(), 32, addrs); - logger.info(transport + " created"); - application.transports.add(transport); - } - } - } - return transport; - } - - protected abstract ClassFilter createServletClassFilter(); - - protected ClassFilter createServiceClassFilter() { - return createClassFilter(this.sncpGroup, null, Service.class, Annotation.class, "services", "service"); - } - - protected ClassFilter createClassFilter(final String localGroup, Class ref, - Class inter, Class ref2, String properties, String property) { - ClassFilter cf = new ClassFilter(ref, inter, null); - if (properties == null && properties == null) return cf; - if (this.nodeConf == null) return cf; - AnyValue[] proplist = this.nodeConf.getAnyValues(properties); - if (proplist == null || proplist.length < 1) return cf; - cf = null; - for (AnyValue list : proplist) { - DefaultAnyValue prop = null; - String sc = list.getValue("groups"); - if (sc == null) sc = localGroup; - if (sc != null) { - prop = new AnyValue.DefaultAnyValue(); - prop.addValue("groups", sc); - } - ClassFilter filter = new ClassFilter(ref, inter, prop); - for (AnyValue av : list.getAnyValues(property)) { - filter.filter(av, av.getValue("value"), false); - } - if (list.getBoolValue("autoload", true)) { - String includes = list.getValue("includes", ""); - String excludes = list.getValue("excludes", ""); - filter.setIncludePatterns(includes.split(";")); - filter.setExcludePatterns(excludes.split(";")); - } else if (ref2 == null || ref2 == Annotation.class) { //service如果是autoload=false则不需要加载 - filter.setRefused(true); - } else if (ref2 != Annotation.class) { - filter.setAnnotationClass(ref2); - } - cf = (cf == null) ? filter : cf.or(filter); - } - return cf; - } - - public abstract InetSocketAddress getSocketAddress(); - - public boolean isSNCP() { - return false; - } - - public InetSocketAddress getSncpAddress() { - return sncpAddress; - } - - public String getSncpGroup() { - return sncpGroup; - } - - public String getNodeProtocol() { - return nodeProtocol; - } - - public void start() throws IOException { - server.start(); - } - - public void shutdown() throws IOException { - final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null; - localServiceWrappers.forEach(y -> { - long s = System.currentTimeMillis(); - y.getService().destroy(y.getConf()); - long e = System.currentTimeMillis() - s; - if (e > 2 && sb != null) { - sb.append("LocalService(").append(y.getType()).append(':').append(y.getName()).append(") destroy ").append(e).append("ms").append(LINE_SEPARATOR); - } - }); - if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString()); - server.shutdown(); - } - -} diff --git a/src/com/wentch/redkale/boot/NodeSncpServer.java b/src/com/wentch/redkale/boot/NodeSncpServer.java deleted file mode 100644 index 37a2d7a65..000000000 --- a/src/com/wentch/redkale/boot/NodeSncpServer.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.boot; - -import com.wentch.redkale.net.*; -import com.wentch.redkale.net.sncp.*; -import com.wentch.redkale.util.*; -import java.net.*; -import java.util.logging.*; - -/** - * - * @author zhangjx - */ -@NodeProtocol({"SNCP"}) -public final class NodeSncpServer extends NodeServer { - - private final SncpServer sncpServer; - - public NodeSncpServer(Application application, AnyValue serconf) { - super(application, application.getResourceFactory().createChild(), createServer(application, serconf)); - this.sncpServer = (SncpServer) this.server; - this.consumer = sncpServer == null ? null : x -> sncpServer.addService(x); - } - - private static Server createServer(Application application, AnyValue serconf) { - return new SncpServer(application.getStartTime(), application.getWatchFactory()); - } - - @Override - public InetSocketAddress getSocketAddress() { - return sncpServer == null ? null : sncpServer.getSocketAddress(); - } - - @Override - public void init(AnyValue config) throws Exception { - super.init(config); - //------------------------------------------------------------------- - if (sncpServer == null) return; //调试时server才可能为null - final StringBuilder sb = logger.isLoggable(Level.FINE) ? new StringBuilder() : null; - final String threadName = "[" + Thread.currentThread().getName() + "] "; - for (SncpServlet en : sncpServer.getSncpServlets()) { - if (sb != null) sb.append(threadName).append(" Loaded ").append(en).append(LINE_SEPARATOR); - } - if (sb != null && sb.length() > 0) logger.log(Level.FINE, sb.toString()); - } - - @Override - public boolean isSNCP() { - return true; - } - - public SncpServer getSncpServer() { - return sncpServer; - } - - @Override - protected void loadServlet(ClassFilter servletFilter) throws Exception { - } - - @Override - protected ClassFilter createServletClassFilter() { - return null; - } - -} diff --git a/src/com/wentch/redkale/convert/AnyEncoder.java b/src/com/wentch/redkale/convert/AnyEncoder.java deleted file mode 100644 index 0a8f253aa..000000000 --- a/src/com/wentch/redkale/convert/AnyEncoder.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.reflect.Type; - -/** - * 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入Writer,JSON则不写入。 - * - * @author zhangjx - * @param - */ -public final class AnyEncoder implements Encodeable { - - final Factory factory; - - AnyEncoder(Factory factory) { - this.factory = factory; - } - - @Override - @SuppressWarnings("unchecked") - public void convertTo(final Writer out, final T value) { - if (value == null) { - out.writeNull(); - } else { - out.wirteClassName(factory.getEntity(value.getClass())); - factory.loadEncoder(value.getClass()).convertTo(out, value); - } - } - - @Override - public Type getType() { - return Object.class; - } - -} diff --git a/src/com/wentch/redkale/convert/ArrayDecoder.java b/src/com/wentch/redkale/convert/ArrayDecoder.java deleted file mode 100644 index fa41b8b3a..000000000 --- a/src/com/wentch/redkale/convert/ArrayDecoder.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.reflect.*; -import java.util.*; - -/** - * 对象数组的序列化,不包含int[]、long[]这样的primitive class数组. - * 数组长度不能超过 32767。 在BSON中数组长度设定的是short,对于大于32767长度的数组传输会影响性能,所以没有采用int存储。 - * 支持一定程度的泛型。 - * - * @author zhangjx - * @param - */ -@SuppressWarnings("unchecked") -public final class ArrayDecoder implements Decodeable { - - private final Type type; - - private final Type componentType; - - private final Class componentClass; - - private final Decodeable decoder; - - public ArrayDecoder(final Factory factory, final Type type) { - this.type = type; - if (type instanceof GenericArrayType) { - Type t = ((GenericArrayType) type).getGenericComponentType(); - this.componentType = t instanceof TypeVariable ? Object.class : t; - } else if ((type instanceof Class) && ((Class) type).isArray()) { - this.componentType = ((Class) type).getComponentType(); - } else { - throw new ConvertException("(" + type + ") is not a array type"); - } - if (this.componentType instanceof ParameterizedType) { - this.componentClass = (Class) ((ParameterizedType) this.componentType).getRawType(); - } else { - this.componentClass = (Class) this.componentType; - } - factory.register(type, this); - this.decoder = factory.loadDecoder(this.componentType); - } - - @Override - public T[] convertFrom(Reader in) { - final int len = in.readArrayB(); - if (len == Reader.SIGN_NULL) return null; - final Decodeable localdecoder = this.decoder; - final List result = new ArrayList(); - if (len == Reader.SIGN_NOLENGTH) { - while (in.hasNext()) { - result.add(localdecoder.convertFrom(in)); - } - } else { - for (int i = 0; i < len; i++) { - result.add(localdecoder.convertFrom(in)); - } - } - in.readArrayE(); - T[] rs = (T[]) Array.newInstance((Class) this.componentClass, result.size()); - return result.toArray(rs); - } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:" + this.decoder + "}"; - } - - @Override - public Type getType() { - return type; - } - -} diff --git a/src/com/wentch/redkale/convert/ArrayEncoder.java b/src/com/wentch/redkale/convert/ArrayEncoder.java deleted file mode 100644 index b75fe4be9..000000000 --- a/src/com/wentch/redkale/convert/ArrayEncoder.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.reflect.*; - -/** - * 对象数组的反序列化,不包含int[]、long[]这样的primitive class数组. - * 数组长度不能超过 32767。 在BSON中数组长度设定的是short,对于大于32767长度的数组传输会影响性能,所以没有采用int存储。 - * 支持一定程度的泛型。 - * - * @author zhangjx - * @param - */ -@SuppressWarnings("unchecked") -public final class ArrayEncoder implements Encodeable { - - private final Type type; - - private final Type componentType; - - private final Encodeable anyEncoder; - - private final Encodeable encoder; - - public ArrayEncoder(final Factory factory, final Type type) { - this.type = type; - if (type instanceof GenericArrayType) { - Type t = ((GenericArrayType) type).getGenericComponentType(); - this.componentType = t instanceof TypeVariable ? Object.class : t; - } else if ((type instanceof Class) && ((Class) type).isArray()) { - this.componentType = ((Class) type).getComponentType(); - } else { - throw new ConvertException("(" + type + ") is not a array type"); - } - factory.register(type, this); - this.encoder = factory.loadEncoder(this.componentType); - this.anyEncoder = factory.getAnyEncoder(); - } - - @Override - public void convertTo(Writer out, T[] value) { - if (value == null) { - out.writeNull(); - return; - } - if (value.length == 0) { - out.writeArrayB(0); - out.writeArrayE(); - return; - } - out.writeArrayB(value.length); - final Type comp = this.componentType; - boolean first = true; - for (Object v : value) { - if (!first) out.writeArrayMark(); - ((v != null && v.getClass() == comp) ? encoder : anyEncoder).convertTo(out, v); - if (first) first = false; - } - out.writeArrayE(); - } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.encoder + "}"; - } - - @Override - public Type getType() { - return type; - } -} diff --git a/src/com/wentch/redkale/convert/CollectionDecoder.java b/src/com/wentch/redkale/convert/CollectionDecoder.java deleted file mode 100644 index df87cfd99..000000000 --- a/src/com/wentch/redkale/convert/CollectionDecoder.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import com.wentch.redkale.util.Creator; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Collection; - -/** - * 对象集合的反序列化. - * 集合大小不能超过 32767。 在BSON中集合大小设定的是short,对于大于32767长度的集合传输会影响性能,所以没有采用int存储。 - * 支持一定程度的泛型。 - * - * @author zhangjx - * @param - */ -@SuppressWarnings("unchecked") -public final class CollectionDecoder implements Decodeable> { - - private final Type type; - - private final Type componentType; - - protected Creator> creator; - - private final Decodeable decoder; - - public CollectionDecoder(final Factory factory, final Type type) { - this.type = type; - if (type instanceof ParameterizedType) { - final ParameterizedType pt = (ParameterizedType) type; - this.componentType = pt.getActualTypeArguments()[0]; - this.creator = factory.loadCreator((Class) pt.getRawType()); - factory.register(type, this); - this.decoder = factory.loadDecoder(this.componentType); - } else { - throw new ConvertException("collectiondecoder not support the type (" + type + ")"); - } - } - - @Override - public Collection convertFrom(Reader in) { - final int len = in.readArrayB(); - if (len == Reader.SIGN_NULL) return null; - final Decodeable localdecoder = this.decoder; - final Collection result = this.creator.create(); - if (len == Reader.SIGN_NOLENGTH) { - while (in.hasNext()) { - result.add(localdecoder.convertFrom(in)); - } - } else { - for (int i = 0; i < len; i++) { - result.add(localdecoder.convertFrom(in)); - } - } - in.readArrayE(); - return result; - } - - @Override - public Type getType() { - return type; - } - -} diff --git a/src/com/wentch/redkale/convert/CollectionEncoder.java b/src/com/wentch/redkale/convert/CollectionEncoder.java deleted file mode 100644 index e823a5775..000000000 --- a/src/com/wentch/redkale/convert/CollectionEncoder.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.reflect.*; -import java.util.Collection; - -/** - * 对象集合的序列化. - * 集合大小不能超过 32767。 在BSON中集合大小设定的是short,对于大于32767长度的集合传输会影响性能,所以没有采用int存储。 - * 支持一定程度的泛型。 - * - * @author zhangjx - * @param - */ -@SuppressWarnings("unchecked") -public final class CollectionEncoder implements Encodeable> { - - private final Type type; - - private final Encodeable encoder; - - public CollectionEncoder(final Factory factory, final Type type) { - this.type = type; - if (type instanceof ParameterizedType) { - Type t = ((ParameterizedType) type).getActualTypeArguments()[0]; - if (t instanceof TypeVariable) { - this.encoder = factory.getAnyEncoder(); - } else { - this.encoder = factory.loadEncoder(t); - } - } else { - this.encoder = factory.getAnyEncoder(); - } - } - - @Override - public void convertTo(Writer out, Collection value) { - if (value == null) { - out.writeNull(); - return; - } - if (value.isEmpty()) { - out.writeArrayB(0); - out.writeArrayE(); - return; - } - out.writeArrayB(value.size()); - boolean first = true; - for (Object v : value) { - if (!first) out.writeArrayMark(); - encoder.convertTo(out, v); - if (first) first = false; - } - out.writeArrayE(); - } - - @Override - public Type getType() { - return type; - } -} diff --git a/src/com/wentch/redkale/convert/Convert.java b/src/com/wentch/redkale/convert/Convert.java deleted file mode 100644 index 61b42ff63..000000000 --- a/src/com/wentch/redkale/convert/Convert.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -/** - * 序列化操作类 - * - * @author zhangjx - * @param - * @param - */ -public abstract class Convert { - - protected final Factory factory; - - protected Convert(Factory factory) { - this.factory = factory; - } - - public Factory getFactory() { - return this.factory; - } -} diff --git a/src/com/wentch/redkale/convert/ConvertColumn.java b/src/com/wentch/redkale/convert/ConvertColumn.java deleted file mode 100644 index 1a868f0c4..000000000 --- a/src/com/wentch/redkale/convert/ConvertColumn.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.*; - -/** - * 依附在setter、getter方法、字段进行简单的配置 - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({METHOD, FIELD}) -@Retention(RUNTIME) -@Repeatable(ConvertColumns.class) -public @interface ConvertColumn { - - /** - * 给字段取个别名, 只对JSON有效 - * - * @return - */ - String name() default ""; - - /** - * 解析/序列化时是否屏蔽该字段 - * - * @return - */ - boolean ignore() default false; - - /** - * 解析/序列化定制化的TYPE - * - * @return - */ - ConvertType type() default ConvertType.ALL; -} diff --git a/src/com/wentch/redkale/convert/ConvertColumnEntry.java b/src/com/wentch/redkale/convert/ConvertColumnEntry.java deleted file mode 100644 index c5339b17a..000000000 --- a/src/com/wentch/redkale/convert/ConvertColumnEntry.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -/** - * ConvertColumn 对应的实体类 - * - * @author zhangjx - */ -public final class ConvertColumnEntry { - - private String name = ""; - - private boolean ignore; - - private ConvertType convertType; - - public ConvertColumnEntry() { - } - - public ConvertColumnEntry(ConvertColumn column) { - if (column == null) return; - this.name = column.name(); - this.ignore = column.ignore(); - this.convertType = column.type(); - } - - public ConvertColumnEntry(String name, boolean ignore) { - this.name = name; - this.ignore = ignore; - this.convertType = ConvertType.ALL; - } - - public ConvertColumnEntry(String name, boolean ignore, ConvertType convertType) { - this.name = name; - this.ignore = ignore; - this.convertType = convertType; - } - - public String name() { - return name == null ? "" : name; - } - - public void setName(String name) { - this.name = name; - } - - public boolean ignore() { - return ignore; - } - - public void setIgnore(boolean ignore) { - this.ignore = ignore; - } - - public ConvertType type() { - return convertType == null ? ConvertType.ALL : convertType; - } - - public void setConvertType(ConvertType convertType) { - this.convertType = convertType; - } - -} diff --git a/src/com/wentch/redkale/convert/ConvertColumns.java b/src/com/wentch/redkale/convert/ConvertColumns.java deleted file mode 100644 index a5e613ad0..000000000 --- a/src/com/wentch/redkale/convert/ConvertColumns.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.*; - -/** - * ConvertColumn 的多用类 - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({METHOD, FIELD}) -@Retention(RUNTIME) -public @interface ConvertColumns { - - ConvertColumn[] value(); -} diff --git a/src/com/wentch/redkale/convert/ConvertEntity.java b/src/com/wentch/redkale/convert/ConvertEntity.java deleted file mode 100644 index 99bd4330c..000000000 --- a/src/com/wentch/redkale/convert/ConvertEntity.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * 用于类名的别名, 类似javax.persistence.Table - * 该值必须是全局唯一 - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({TYPE}) -@Retention(RUNTIME) -public @interface ConvertEntity { - - String value(); -} diff --git a/src/com/wentch/redkale/convert/ConvertException.java b/src/com/wentch/redkale/convert/ConvertException.java deleted file mode 100644 index 338e1f44e..000000000 --- a/src/com/wentch/redkale/convert/ConvertException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -/** - * - * @author zhangjx - */ -public class ConvertException extends RuntimeException { - - public ConvertException() { - super(); - } - - public ConvertException(String s) { - super(s); - } - - public ConvertException(String message, Throwable cause) { - super(message, cause); - } - - public ConvertException(Throwable cause) { - super(cause); - } -} diff --git a/src/com/wentch/redkale/convert/ConvertType.java b/src/com/wentch/redkale/convert/ConvertType.java deleted file mode 100644 index 7871a01d8..000000000 --- a/src/com/wentch/redkale/convert/ConvertType.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -/** - * - * @author zhangjx - */ -public enum ConvertType { - - JSON(1), - BSON(2), - ALL(127); - - private final int value; - - private ConvertType(int v) { - this.value = v; - } - - public boolean contains(ConvertType type) { - if (type == null) return false; - return this.value >= type.value && (this.value & type.value) > 0; - } -} diff --git a/src/com/wentch/redkale/convert/DeMember.java b/src/com/wentch/redkale/convert/DeMember.java deleted file mode 100644 index 2897e7d23..000000000 --- a/src/com/wentch/redkale/convert/DeMember.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import com.wentch.redkale.util.Attribute; - -/** - * - * @author zhangjx - * @param - * @param - * @param - */ -@SuppressWarnings("unchecked") -public final class DeMember implements Comparable> { - - protected final Attribute attribute; - - protected Decodeable decoder; - - public DeMember(final Attribute attribute) { - this.attribute = attribute; - } - - public DeMember(Attribute attribute, Decodeable decoder) { - this(attribute); - this.decoder = decoder; - } - - public final void read(R in, T obj) { - this.attribute.set(obj, decoder.convertFrom(in)); - } - - public Attribute getAttribute() { - return this.attribute; - } - - @Override - public final int compareTo(DeMember o) { - if (o == null) return 1; - return this.attribute.field().compareTo(o.attribute.field()); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (!(obj instanceof DeMember)) return false; - DeMember other = (DeMember) obj; - return compareTo(other) == 0; - } - - @Override - public int hashCode() { - return this.attribute.field().hashCode(); - } - - @Override - public String toString() { - return "DeMember{" + "attribute=" + attribute.field() + ", decoder=" + decoder + '}'; - } -} diff --git a/src/com/wentch/redkale/convert/Decodeable.java b/src/com/wentch/redkale/convert/Decodeable.java deleted file mode 100644 index c6b58899a..000000000 --- a/src/com/wentch/redkale/convert/Decodeable.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.reflect.Type; - -/** - * - * @author zhangjx - * @param - * @param - */ -public interface Decodeable { - - public T convertFrom(final R in); - - /** - * 泛型映射接口 - * - * @return - */ - public Type getType(); - -} diff --git a/src/com/wentch/redkale/convert/EnMember.java b/src/com/wentch/redkale/convert/EnMember.java deleted file mode 100644 index beb71576e..000000000 --- a/src/com/wentch/redkale/convert/EnMember.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import com.wentch.redkale.util.Attribute; - -/** - * - * @author zhangjx - * @param - * @param - * @param - */ -@SuppressWarnings("unchecked") -public final class EnMember implements Comparable> { - - private final Attribute attribute; - - final Encodeable encoder; - - private final boolean istring; - - //private final boolean isnumber; - private final boolean isbool; - - public EnMember(Attribute attribute, Encodeable encoder) { - this.attribute = attribute; - this.encoder = encoder; - Class t = attribute.type(); - this.istring = CharSequence.class.isAssignableFrom(t); - this.isbool = t == Boolean.class || t == boolean.class; - //this.isnumber = Number.class.isAssignableFrom(t) || (!this.isbool && t.isPrimitive()); - } - - public boolean write(final W out, final boolean comma, final T obj) { - F value = attribute.get(obj); - if (value == null) return comma; - if (out.isTiny()) { - if (istring) { - if (((CharSequence) value).length() == 0) return comma; - } else if (isbool) { - if (!((Boolean) value)) return comma; - } - } - out.writeField(comma, attribute); - encoder.convertTo(out, value); - return true; - } - - @Override - public final int compareTo(EnMember o) { - if (o == null) return 1; - return this.attribute.field().compareTo(o.attribute.field()); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (!(obj instanceof EnMember)) return false; - EnMember other = (EnMember) obj; - return compareTo(other) == 0; - } - - @Override - public int hashCode() { - return this.attribute.field().hashCode(); - } - - @Override - public String toString() { - return "EnMember{" + "attribute=" + attribute.field() + ", encoder=" + encoder + '}'; - } -} diff --git a/src/com/wentch/redkale/convert/Encodeable.java b/src/com/wentch/redkale/convert/Encodeable.java deleted file mode 100644 index 595383445..000000000 --- a/src/com/wentch/redkale/convert/Encodeable.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.reflect.Type; - -/** - * - * @author zhangjx - * @param - * @param - */ -public interface Encodeable { - - public void convertTo(final W out, T value); - - /** - * 泛型映射接口 - * - * @return - */ - public Type getType(); - -} diff --git a/src/com/wentch/redkale/convert/Factory.java b/src/com/wentch/redkale/convert/Factory.java deleted file mode 100644 index 95c0649ba..000000000 --- a/src/com/wentch/redkale/convert/Factory.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import com.wentch.redkale.convert.ext.*; -import com.wentch.redkale.util.*; -import java.lang.reflect.Type; -import java.util.Collection; -import java.util.Map; -import java.lang.reflect.*; -import java.math.BigInteger; -import java.net.*; -import static com.wentch.redkale.convert.ext.InetAddressSimpledCoder.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.regex.*; - -/** - * - * @author zhangjx - * @param - * @param - */ -@SuppressWarnings("unchecked") -public abstract class Factory { - - private final Factory parent; - - protected Convert convert; - - protected boolean tiny; - - private final Encodeable anyEncoder = new AnyEncoder(this); - - //----------------------------------------------------------------------------------- - private final HashedMap creators = new HashedMap(); - - private final Map entitys = new ConcurrentHashMap(); - - private final HashedMap> decoders = new HashedMap(); - - private final HashedMap> encoders = new HashedMap(); - - private final HashMap columnEntrys = new HashMap(); - - private final Set skipIgnores = new HashSet(); - - private boolean skipAllIgnore = false; - - protected Factory(Factory parent, boolean tiny) { - this.tiny = tiny; - this.parent = parent; - if (parent == null) { - //--------------------------------------------------------- - this.register(boolean.class, BoolSimpledCoder.instance); - this.register(Boolean.class, BoolSimpledCoder.instance); - - this.register(byte.class, ByteSimpledCoder.instance); - this.register(Byte.class, ByteSimpledCoder.instance); - - this.register(short.class, ShortSimpledCoder.instance); - this.register(Short.class, ShortSimpledCoder.instance); - - this.register(char.class, CharSimpledCoder.instance); - this.register(Character.class, CharSimpledCoder.instance); - - this.register(int.class, IntSimpledCoder.instance); - this.register(Integer.class, IntSimpledCoder.instance); - - this.register(long.class, LongSimpledCoder.instance); - this.register(Long.class, LongSimpledCoder.instance); - - this.register(float.class, FloatSimpledCoder.instance); - this.register(Float.class, FloatSimpledCoder.instance); - - this.register(double.class, DoubleSimpledCoder.instance); - this.register(Double.class, DoubleSimpledCoder.instance); - - this.register(Number.class, NumberSimpledCoder.instance); - this.register(String.class, StringSimpledCoder.instance); - this.register(java.util.Date.class, DateSimpledCoder.instance); - this.register(BigInteger.class, BigIntegerSimpledCoder.instance); - this.register(InetAddress.class, InetAddressSimpledCoder.instance); - this.register(DLong.class, DLongSimpledCoder.instance); - this.register(Class.class, TypeSimpledCoder.instance); - this.register(InetSocketAddress.class, InetSocketAddressSimpledCoder.instance); - this.register(Pattern.class, PatternSimpledCoder.instance); - //--------------------------------------------------------- - this.register(boolean[].class, BoolArraySimpledCoder.instance); - this.register(byte[].class, ByteArraySimpledCoder.instance); - this.register(short[].class, ShortArraySimpledCoder.instance); - this.register(char[].class, CharArraySimpledCoder.instance); - this.register(int[].class, IntArraySimpledCoder.instance); - this.register(long[].class, LongArraySimpledCoder.instance); - this.register(float[].class, FloatArraySimpledCoder.instance); - this.register(double[].class, DoubleArraySimpledCoder.instance); - this.register(String[].class, StringArraySimpledCoder.instance); - //--------------------------------------------------------- - } - } - - public Factory parent() { - return this.parent; - } - - public abstract ConvertType getConvertType(); - - public abstract boolean isReversible(); - - public abstract Factory createChild(); - - public abstract Factory createChild(boolean tiny); - - public Convert getConvert() { - return convert; - } - - public void setTiny(boolean tiny) { - this.tiny = tiny; - } - - public ConvertColumnEntry findRef(AccessibleObject field) { - if (field == null) return null; - ConvertColumnEntry en = this.columnEntrys.get(field); - if (en != null) return en; - final ConvertType ct = this.getConvertType(); - for (ConvertColumn ref : field.getAnnotationsByType(ConvertColumn.class)) { - if (ref.type().contains(ct)) { - ConvertColumnEntry entry = new ConvertColumnEntry(ref); - if (skipAllIgnore) { - entry.setIgnore(false); - return entry; - } - if (skipIgnores.isEmpty()) return entry; - if (skipIgnores.contains(((Member) field).getDeclaringClass())) entry.setIgnore(false); - return entry; - } - } - return null; - } - - final String getEntity(Class clazz) { - ConvertEntity ce = (ConvertEntity) clazz.getAnnotation(ConvertEntity.class); - if (ce != null && findEntity(ce.value()) == null) entitys.put(ce.value(), clazz); - return ce == null ? clazz.getName() : ce.value(); - } - - private Class findEntity(String name) { - Class clazz = entitys.get(name); - return parent == null ? clazz : parent.findEntity(name); - } - - final Class getEntity(String name) { - Class clazz = findEntity(name); - try { - return clazz == null ? Class.forName(name) : clazz; - } catch (Exception ex) { - throw new ConvertException("convert entity is " + name, ex); - } - } - - /** - * 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false - *

- * @param skipIgnore - */ - public final void registerSkipAllIgnore(final boolean skipIgnore) { - this.skipAllIgnore = skipIgnore; - } - - /** - * 使该类所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false - *

- * @param type - */ - public final void registerSkipIgnore(final Class type) { - skipIgnores.add(type); - } - - public final void register(final Class type, boolean ignore, String... columns) { - for (String column : columns) { - register(type, column, new ConvertColumnEntry(column, ignore)); - } - } - - public final boolean register(final Class type, String column, ConvertColumnEntry entry) { - if (type == null || column == null || entry == null) return false; - try { - final Field field = type.getDeclaredField(column); - String get = "get"; - if (field.getType() == boolean.class || field.getType() == Boolean.class) get = "is"; - char[] cols = column.toCharArray(); - cols[0] = Character.toUpperCase(cols[0]); - String col2 = new String(cols); - try { - register(type.getMethod(get + col2), entry); - } catch (Exception ex) { - } - try { - register(type.getMethod("set" + col2, field.getType()), entry); - } catch (Exception ex) { - } - return register(field, entry); - } catch (Exception e) { - return false; - } - } - - public final boolean register(final AccessibleObject field, final ConvertColumnEntry entry) { - if (field == null || entry == null) return false; - this.columnEntrys.put(field, entry); - return true; - } - - public final void register(final Class clazz, final Creator creator) { - creators.put(clazz, creator); - } - - public final Creator findCreator(Class type) { - Creator creator = creators.get(type); - if (creator != null) return creator; - return this.parent == null ? null : this.parent.findCreator(type); - } - - public final Creator loadCreator(Class type) { - Creator result = findCreator(type); - if (result == null) { - result = Creator.create(type); - creators.put(type, result); - } - return result; - } - - //---------------------------------------------------------------------- - public final Encodeable getAnyEncoder() { - return (Encodeable) anyEncoder; - } - - public final void register(final Type clazz, final SimpledCoder coder) { - decoders.put(clazz, coder); - encoders.put(clazz, coder); - } - - public final void register(final Type clazz, final Decodeable decoder) { - decoders.put(clazz, decoder); - } - - public final void register(final Type clazz, final Encodeable printer) { - encoders.put(clazz, printer); - } - - public final Decodeable findDecoder(final Type type) { - Decodeable rs = (Decodeable) decoders.get(type); - if (rs != null) return rs; - return this.parent == null ? null : this.parent.findDecoder(type); - } - - public final Encodeable findEncoder(final Type type) { - Encodeable rs = (Encodeable) encoders.get(type); - if (rs != null) return rs; - return this.parent == null ? null : this.parent.findEncoder(type); - } - - public final Decodeable loadDecoder(final Type type) { - Decodeable decoder = findDecoder(type); - if (decoder != null) return decoder; - if (type instanceof GenericArrayType) return new ArrayDecoder(this, type); - Class clazz; - if (type instanceof ParameterizedType) { - final ParameterizedType pts = (ParameterizedType) type; - clazz = (Class) (pts).getRawType(); - } else if (type instanceof Class) { - clazz = (Class) type; - } else { - throw new ConvertException("not support the type (" + type + ")"); - } - decoder = findDecoder(clazz); - if (decoder != null) return decoder; - return createDecoder(type, clazz); - } - - public final Decodeable createDecoder(final Type type) { - Class clazz; - if (type instanceof ParameterizedType) { - final ParameterizedType pts = (ParameterizedType) type; - clazz = (Class) (pts).getRawType(); - } else if (type instanceof Class) { - clazz = (Class) type; - } else { - throw new ConvertException("not support the type (" + type + ")"); - } - return createDecoder(type, clazz); - } - - private Decodeable createDecoder(final Type type, final Class clazz) { - Decodeable decoder = null; - ObjectDecoder od = null; - if (clazz.isEnum()) { - decoder = new EnumSimpledCoder(clazz); - } else if (clazz.isArray()) { - decoder = new ArrayDecoder(this, type); - } else if (Collection.class.isAssignableFrom(clazz)) { - decoder = new CollectionDecoder(this, type); - } else if (Map.class.isAssignableFrom(clazz)) { - decoder = new MapDecoder(this, type); - } else if (clazz == Object.class) { - od = new ObjectDecoder(type); - decoder = od; - } else if (!clazz.getName().startsWith("java.")) { - od = new ObjectDecoder(type); - decoder = od; - } - if (decoder == null) throw new ConvertException("not support the type (" + type + ")"); - register(type, decoder); - if (od != null) od.init(this); - return decoder; - } - - public final Encodeable loadEncoder(final Type type) { - Encodeable encoder = findEncoder(type); - if (encoder != null) return encoder; - if (type instanceof GenericArrayType) return new ArrayEncoder(this, type); - Class clazz; - if (type instanceof ParameterizedType) { - final ParameterizedType pts = (ParameterizedType) type; - clazz = (Class) (pts).getRawType(); - } else if (type instanceof TypeVariable) { - TypeVariable tv = (TypeVariable) type; - Type t = Object.class; - if (tv.getBounds().length == 1) { - t = tv.getBounds()[0]; - } - if (!(t instanceof Class)) t = Object.class; - clazz = (Class) t; - } else if (type instanceof Class) { - clazz = (Class) type; - } else { - throw new ConvertException("not support the type (" + type + ")"); - } - encoder = findEncoder(clazz); - if (encoder != null) return encoder; - return createEncoder(type, clazz); - } - - public final Encodeable createEncoder(final Type type) { - Class clazz; - if (type instanceof ParameterizedType) { - final ParameterizedType pts = (ParameterizedType) type; - clazz = (Class) (pts).getRawType(); - } else if (type instanceof Class) { - clazz = (Class) type; - } else { - throw new ConvertException("not support the type (" + type + ")"); - } - return createEncoder(type, clazz); - } - - private Encodeable createEncoder(final Type type, final Class clazz) { - Encodeable encoder = null; - ObjectEncoder oe = null; - if (clazz.isEnum()) { - encoder = new EnumSimpledCoder(clazz); - } else if (clazz.isArray()) { - encoder = new ArrayEncoder(this, type); - } else if (Collection.class.isAssignableFrom(clazz)) { - encoder = new CollectionEncoder(this, type); - } else if (Map.class.isAssignableFrom(clazz)) { - encoder = new MapEncoder(this, type); - } else if (clazz == Object.class) { - return (Encodeable) this.anyEncoder; - } else if (!clazz.getName().startsWith("java.")) { - oe = new ObjectEncoder(type); - encoder = oe; - } - if (encoder == null) throw new ConvertException("not support the type (" + type + ")"); - register(type, encoder); - if (oe != null) oe.init(this); - return encoder; - - } - -} diff --git a/src/com/wentch/redkale/convert/HashedMap.java b/src/com/wentch/redkale/convert/HashedMap.java deleted file mode 100644 index db583032e..000000000 --- a/src/com/wentch/redkale/convert/HashedMap.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.reflect.*; - -/** - * 只增不减的伪Map类 - * - * @author zhangjx - * @param - * @param - */ -@SuppressWarnings("unchecked") -public final class HashedMap { - - protected final transient Entry[] table; - - public HashedMap() { - this(128); - } - - public HashedMap(int initCapacity) { - this.table = new Entry[Math.max(initCapacity, 16)]; - } - - public final V get(final K key) { - final K k = key; - final Entry[] data = this.table; - Entry entry = data[k.hashCode() & (data.length - 1)]; - while (entry != null) { - if (k == entry.key) return entry.value; - entry = entry.next; - } - return null; - } - - public final V put(K key, V value) { - final K k = key; - final Entry[] data = this.table; - final int index = k.hashCode() & (data.length - 1); - Entry entry = data[index]; - while (entry != null) { - if (k == entry.key) { - entry.value = value; - return entry.value; - } - entry = entry.next; - } - data[index] = new Entry(key, value, data[index]); - return null; - } - - protected static final class Entry { - - protected V value; - - protected final K key; - - protected final Entry next; - - protected Entry(K key, V value, Entry next) { - this.key = key; - this.value = value; - this.next = next; - } - } -} diff --git a/src/com/wentch/redkale/convert/MapDecoder.java b/src/com/wentch/redkale/convert/MapDecoder.java deleted file mode 100644 index dfd7c2c1e..000000000 --- a/src/com/wentch/redkale/convert/MapDecoder.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import com.wentch.redkale.util.Creator; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Map; - -/** - * - * @author zhangjx - * @param - * @param - */ -@SuppressWarnings("unchecked") -public final class MapDecoder implements Decodeable> { - - private final Type type; - - private final Type keyType; - - private final Type valueType; - - protected Creator> creator; - - private final Decodeable keyDecoder; - - private final Decodeable valueDecoder; - - public MapDecoder(final Factory factory, final Type type) { - this.type = type; - if (type instanceof ParameterizedType) { - final ParameterizedType pt = (ParameterizedType) type; - this.keyType = pt.getActualTypeArguments()[0]; - this.valueType = pt.getActualTypeArguments()[1]; - this.creator = factory.loadCreator((Class) pt.getRawType()); - factory.register(type, this); - this.keyDecoder = factory.loadDecoder(this.keyType); - this.valueDecoder = factory.loadDecoder(this.valueType); - } else { - throw new ConvertException("mapdecoder not support the type (" + type + ")"); - } - } - - @Override - public Map convertFrom(Reader in) { - final int len = in.readMapB(); - if (len == Reader.SIGN_NULL) return null; - final Map result = this.creator.create(); - if (len == Reader.SIGN_NOLENGTH) { - while (in.hasNext()) { - K key = keyDecoder.convertFrom(in); - in.skipBlank(); - V value = valueDecoder.convertFrom(in); - result.put(key, value); - } - } else { - for (int i = 0; i < len; i++) { - K key = keyDecoder.convertFrom(in); - in.skipBlank(); - V value = valueDecoder.convertFrom(in); - result.put(key, value); - } - } - in.readMapE(); - return result; - } - - @Override - public Type getType() { - return this.type; - } - -} diff --git a/src/com/wentch/redkale/convert/MapEncoder.java b/src/com/wentch/redkale/convert/MapEncoder.java deleted file mode 100644 index b4c12ff39..000000000 --- a/src/com/wentch/redkale/convert/MapEncoder.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Map; - -/** - * - * @author zhangjx - * @param - * @param - */ -@SuppressWarnings("unchecked") -public final class MapEncoder implements Encodeable> { - - private final Type type; - - private final Encodeable keyencoder; - - private final Encodeable valencoder; - - public MapEncoder(final Factory factory, final Type type) { - this.type = type; - if (type instanceof ParameterizedType) { - final Type[] pt = ((ParameterizedType) type).getActualTypeArguments(); - this.keyencoder = factory.loadEncoder(pt[0]); - this.valencoder = factory.loadEncoder(pt[1]); - } else { - this.keyencoder = factory.getAnyEncoder(); - this.valencoder = factory.getAnyEncoder(); - } - } - - @Override - public void convertTo(Writer out, Map value) { - final Map values = value; - if (values == null) { - out.writeNull(); - return; - } - out.writeMapB(values.size()); - boolean first = true; - for (Map.Entry en : values.entrySet()) { - if (!first) out.writeArrayMark(); - this.keyencoder.convertTo(out, en.getKey()); - out.writeMapMark(); - this.valencoder.convertTo(out, en.getValue()); - if (first) first = false; - } - out.writeMapE(); - } - - @Override - public Type getType() { - return type; - } -} diff --git a/src/com/wentch/redkale/convert/ObjectDecoder.java b/src/com/wentch/redkale/convert/ObjectDecoder.java deleted file mode 100644 index 80600ff71..000000000 --- a/src/com/wentch/redkale/convert/ObjectDecoder.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import static com.wentch.redkale.convert.ObjectEncoder.TYPEZERO; -import com.wentch.redkale.util.Creator; -import java.lang.reflect.*; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * - * @author zhangjx - * @param - * @param - */ -@SuppressWarnings("unchecked") -public final class ObjectDecoder implements Decodeable { - - protected final Type type; - - protected final Class typeClass; - - protected Creator creator; - - protected DeMember[] members; - - protected Factory factory; - - private boolean inited = false; - - private final Object lock = new Object(); - - protected ObjectDecoder(Type type) { - this.type = ((type instanceof Class) && ((Class) type).isInterface()) ? Object.class : type; - if (type instanceof ParameterizedType) { - final ParameterizedType pt = (ParameterizedType) type; - this.typeClass = (Class) pt.getRawType(); - } else { - this.typeClass = (Class) type; - } - this.members = new DeMember[0]; - } - - public void init(final Factory factory) { - this.factory = factory; - try { - if (type == Object.class) return; - - Class clazz = null; - if (type instanceof ParameterizedType) { - final ParameterizedType pts = (ParameterizedType) type; - clazz = (Class) (pts).getRawType(); - } else if (!(type instanceof Class)) { - throw new ConvertException("[" + type + "] is no a class"); - } else { - clazz = (Class) type; - } - final Type[] virGenericTypes = this.typeClass.getTypeParameters(); - final Type[] realGenericTypes = (type instanceof ParameterizedType) ? ((ParameterizedType) type).getActualTypeArguments() : TYPEZERO; - this.creator = factory.loadCreator(clazz); - final Set list = new HashSet(); - try { - ConvertColumnEntry ref; - for (final Field field : clazz.getFields()) { - if (Modifier.isStatic(field.getModifiers())) continue; - ref = factory.findRef(field); - if (ref != null && ref.ignore()) continue; - Type t = ObjectEncoder.makeGenericType(field.getGenericType(), virGenericTypes, realGenericTypes); - list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), factory.loadDecoder(t))); - } - final boolean reversible = factory.isReversible(); - for (final Method method : clazz.getMethods()) { - if (Modifier.isStatic(method.getModifiers())) continue; - if (Modifier.isAbstract(method.getModifiers())) continue; - if (method.isSynthetic()) continue; - if (method.getName().length() < 4) continue; - if (!method.getName().startsWith("set")) continue; - if (method.getParameterTypes().length != 1) continue; - if (method.getReturnType() != void.class) continue; - if (reversible) { - boolean is = method.getParameterTypes()[0] == boolean.class || method.getParameterTypes()[0] == Boolean.class; - try { - clazz.getMethod(method.getName().replaceFirst("set", is ? "is" : "get")); - } catch (Exception e) { - continue; - } - } - ref = factory.findRef(method); - if (ref != null && ref.ignore()) continue; - Type t = ObjectEncoder.makeGenericType(method.getGenericParameterTypes()[0], virGenericTypes, realGenericTypes); - list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), factory.loadDecoder(t))); - } - this.members = list.toArray(new DeMember[list.size()]); - Arrays.sort(this.members); - } catch (Exception ex) { - throw new ConvertException(ex); - } - } finally { - inited = true; - synchronized (lock) { - lock.notifyAll(); - } - } - } - - /** - * 对象格式: [0x1][short字段个数][字段名][字段值]...[0x2] - * - * @param in - * @return - */ - @Override - public final T convertFrom(final R in) { - final String clazz = in.readClassName(); - if (clazz != null && !clazz.isEmpty()) return (T) factory.loadDecoder(factory.getEntity(clazz)).convertFrom(in); - if (in.readObjectB() == Reader.SIGN_NULL) return null; - if (!this.inited) { - synchronized (lock) { - try { - lock.wait(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - final T result = this.creator.create(); - final AtomicInteger index = new AtomicInteger(); - while (in.hasNext()) { - DeMember member = in.readField(index, members); - in.skipBlank(); - if (member == null) { - in.skipValue(); //跳过该属性的值 - } else { - member.read(in, result); - } - index.incrementAndGet(); - } - in.readObjectE(); - return result; - } - - @Override - public final Type getType() { - return this.type; - } - - @Override - public String toString() { - return "ObjectDecoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}'; - } -} diff --git a/src/com/wentch/redkale/convert/ObjectEncoder.java b/src/com/wentch/redkale/convert/ObjectEncoder.java deleted file mode 100644 index 939b9e2c8..000000000 --- a/src/com/wentch/redkale/convert/ObjectEncoder.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import com.wentch.redkale.util.Attribute; -import java.lang.reflect.*; -import java.util.*; - -/** - * - * @author zhangjx - * @param - * @param - */ -@SuppressWarnings("unchecked") -public final class ObjectEncoder implements Encodeable { - - static final Type[] TYPEZERO = new Type[0]; - - protected final Type type; - - protected final Class typeClass; - - protected EnMember[] members; - - protected Factory factory; - - private boolean inited = false; - - private final Object lock = new Object(); - - protected ObjectEncoder(Type type) { - this.type = type; - if (type instanceof ParameterizedType) { - final ParameterizedType pt = (ParameterizedType) type; - this.typeClass = (Class) pt.getRawType(); - } else { - this.typeClass = (Class) type; - } - this.members = new EnMember[0]; - } - - static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) { - if (type instanceof Class) { - return type; - } else if (type instanceof ParameterizedType) { - final ParameterizedType pt = (ParameterizedType) type; - Type[] paramTypes = pt.getActualTypeArguments(); - final Type[] newTypes = new Type[paramTypes.length]; - int count = 0; - for (int i = 0; i < newTypes.length; i++) { - newTypes[i] = makeGenericType(paramTypes[i], virGenericTypes, realGenericTypes); - if (paramTypes[i] == newTypes[i]) count++; - } - if (count == paramTypes.length) return pt; - return new ParameterizedType() { - - @Override - public Type[] getActualTypeArguments() { - return newTypes; - } - - @Override - public Type getRawType() { - return pt.getRawType(); - } - - @Override - public Type getOwnerType() { - return pt.getOwnerType(); - } - - }; - } - if (realGenericTypes == null) return type; - if (type instanceof WildcardType) { - final WildcardType wt = (WildcardType) type; - for (Type f : wt.getUpperBounds()) { - for (int i = 0; i < virGenericTypes.length; i++) { - if (virGenericTypes[i] == f) return realGenericTypes.length == 0 ? Object.class : realGenericTypes[i]; - } - } - } else if (type instanceof TypeVariable) { - for (int i = 0; i < virGenericTypes.length; i++) { - if (virGenericTypes[i] == type) return i >= realGenericTypes.length ? Object.class : realGenericTypes[i]; - } - } - return type; - } - - private static String readGetSetFieldName(Method method) { - if (method == null) return null; - String fname = method.getName(); - if (!fname.startsWith("is") && !fname.startsWith("get") && !fname.startsWith("set")) return fname; - fname = fname.substring(fname.startsWith("is") ? 2 : 3); - if (fname.length() > 1 && !(fname.charAt(1) >= 'A' && fname.charAt(1) <= 'Z')) { - fname = Character.toLowerCase(fname.charAt(0)) + fname.substring(1); - } else if (fname.length() == 1) { - fname = "" + Character.toLowerCase(fname.charAt(0)); - } - return fname; - } - - static Attribute createAttribute(final Factory factory, Class clazz, final Field field, final Method getter, final Method setter) { - String fieldalias = null; - if (field != null) { // public field - ConvertColumnEntry ref = factory.findRef(field); - fieldalias = ref == null || ref.name().isEmpty() ? field.getName() : ref.name(); - } else if (getter != null) { - ConvertColumnEntry ref = factory.findRef(getter); - String mfieldname = readGetSetFieldName(getter); - if (ref == null) { - try { - ref = factory.findRef(clazz.getDeclaredField(mfieldname)); - } catch (Exception e) { - } - } - fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name(); - } else { // setter != null - ConvertColumnEntry ref = factory.findRef(setter); - String mfieldname = readGetSetFieldName(setter); - if (ref == null) { - try { - ref = factory.findRef(clazz.getDeclaredField(mfieldname)); - } catch (Exception e) { - } - } - fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name(); - } - return Attribute.create(clazz, fieldalias, field, getter, setter); - } - - public void init(final Factory factory) { - this.factory = factory; - try { - if (type == Object.class) return; - //if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class"); - final Class clazz = this.typeClass; - final Set list = new HashSet(); - final Type[] virGenericTypes = this.typeClass.getTypeParameters(); - final Type[] realGenericTypes = (type instanceof ParameterizedType) ? ((ParameterizedType) type).getActualTypeArguments() : null; - if (realGenericTypes != null) { - // println(type + "," + Arrays.toString(virGenericTypes) + ", " + Arrays.toString(realGenericTypes)); - } - try { - ConvertColumnEntry ref; - for (final Field field : clazz.getFields()) { - if (Modifier.isStatic(field.getModifiers())) continue; - ref = factory.findRef(field); - if (ref != null && ref.ignore()) continue; - Type t = makeGenericType(field.getGenericType(), virGenericTypes, realGenericTypes); - list.add(new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t))); - } - final boolean reversible = factory.isReversible(); - for (final Method method : clazz.getMethods()) { - if (Modifier.isStatic(method.getModifiers())) continue; - if (Modifier.isAbstract(method.getModifiers())) continue; - if (method.isSynthetic()) continue; - if (method.getName().length() < 3) continue; - if (method.getName().equals("getClass")) continue; - if (!method.getName().startsWith("is") && !method.getName().startsWith("get")) continue; - if (method.getParameterTypes().length != 0) continue; - if (method.getReturnType() == void.class) continue; - if (reversible) { - boolean is = method.getName().startsWith("is"); - try { - clazz.getMethod(method.getName().replaceFirst(is ? "is" : "get", "set"), method.getReturnType()); - } catch (Exception e) { - continue; - } - } - ref = factory.findRef(method); - if (ref != null && ref.ignore()) continue; - Type t = makeGenericType(method.getGenericReturnType(), virGenericTypes, realGenericTypes); - list.add(new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t))); - } - this.members = list.toArray(new EnMember[list.size()]); - Arrays.sort(this.members); - - } catch (Exception ex) { - throw new ConvertException(ex); - } - } finally { - inited = true; - synchronized (lock) { - lock.notifyAll(); - } - } - } - - @Override - public final void convertTo(W out, T value) { - if (value == null) { - out.wirteClassName(null); - out.writeNull(); - return; - } - if (!this.inited) { - synchronized (lock) { - try { - lock.wait(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - if (value != null && value.getClass() != this.typeClass) { - final Class clz = value.getClass(); - out.wirteClassName(factory.getEntity(clz)); - factory.loadEncoder(clz).convertTo(out, value); - return; - } - out.writeObjectB(members.length, value); - boolean comma = false; - for (EnMember member : members) { - comma = member.write(out, comma, value); - } - out.writeObjectE(value); - } - - @Override - public final Type getType() { - return this.type; - } - - @Override - public String toString() { - return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}'; - } -} diff --git a/src/com/wentch/redkale/convert/Reader.java b/src/com/wentch/redkale/convert/Reader.java deleted file mode 100644 index ba40ed756..000000000 --- a/src/com/wentch/redkale/convert/Reader.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * - * @author zhangjx - */ -public interface Reader { - - public static final short SIGN_NULL = -1; - - public static final short SIGN_NOLENGTH = -2; - - /** - * 是否还存在下个元素或字段 - * - * @return - */ - public boolean hasNext(); - - /** - * 跳过值(不包含值前面的字段) - */ - public void skipValue(); - - /** - * /跳过字段与值之间的多余内容, json就是跳过:符, map跳过: - */ - public void skipBlank(); - - /** - * 读取对象的开头 返回字段数 - * - * @return - */ - public int readObjectB(); - - /** - * 读取对象的尾端 - * - */ - public void readObjectE(); - - /** - * 读取数组的开头并返回数组的长度 - * - * @return - */ - public int readArrayB(); - - /** - * 读取数组的尾端 - * - */ - public void readArrayE(); - - /** - * 读取map的开头并返回map的size - * - * @return - */ - public int readMapB(); - - /** - * 读取数组的尾端 - * - */ - public void readMapE(); - - /** - * 根据字段读取字段对应的DeMember - * - * @param index - * @param members - * @return - */ - public DeMember readField(final AtomicInteger index, final DeMember[] members); - - public boolean readBoolean(); - - public byte readByte(); - - public char readChar(); - - public short readShort(); - - public int readInt(); - - public long readLong(); - - public float readFloat(); - - public double readDouble(); - - /** - * 读取无转义字符长度不超过255的字符串, 例如枚举值、字段名、类名字符串等 - * - * @return - */ - public String readSmallString(); - - public String readClassName(); - - public String readString(); - -} diff --git a/src/com/wentch/redkale/convert/SimpledCoder.java b/src/com/wentch/redkale/convert/SimpledCoder.java deleted file mode 100644 index db0e42657..000000000 --- a/src/com/wentch/redkale/convert/SimpledCoder.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; - -/** - * - * @author zhangjx - * @param - * @param - * @param - */ -public abstract class SimpledCoder implements Decodeable, Encodeable { - - private Type type; - - @Override - public abstract void convertTo(final W out, final T value); - - @Override - public abstract T convertFrom(final R in); - - @Override - @SuppressWarnings("unchecked") - public Class getType() { - if (type == null) { - Type[] ts = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments(); - type = ts[ts.length - 1]; - } - return (Class) type; - } - - @Override - public String toString() { - return this.getClass().getSimpleName(); - } -} diff --git a/src/com/wentch/redkale/convert/Writer.java b/src/com/wentch/redkale/convert/Writer.java deleted file mode 100644 index adcba5e91..000000000 --- a/src/com/wentch/redkale/convert/Writer.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert; - -import com.wentch.redkale.util.Attribute; - -/** - * - * @author zhangjx - */ -public interface Writer { - - /** - * 当tiny=true时, 字符串为空、boolean为false的字段值都会被跳过, 不会输出。 - *

- * @return - */ - public boolean isTiny(); - - /** - * 输出null值 - */ - public void writeNull(); - - /** - * - * @param clazz - */ - public void wirteClassName(String clazz); - - /** - * 输出一个对象前的操作 - * - * @param fieldCount 字段个数 - * - * @param obj - */ - public void writeObjectB(int fieldCount, Object obj); - - /** - * 输出一个对象后的操作 - * - * @param obj - */ - public void writeObjectE(Object obj); - - /** - * 输出一个数组前的操作 - * - * @param size 数组长度 - */ - public void writeArrayB(int size); - - /** - * 输出数组元素间的间隔符 - * - */ - public void writeArrayMark(); - - /** - * 输出一个数组后的操作 - * - */ - public void writeArrayE(); - - /** - * 输出一个Map前的操作 - * - * @param size map大小 - */ - public void writeMapB(int size); - - /** - * 输出一个Map中key与value间的间隔符 - * - */ - public void writeMapMark(); - - /** - * 输出一个Map后的操作 - * - */ - public void writeMapE(); - - /** - * 输出一个字段 - * - * @param comma 是否非第一个字段 - * @param attribute - */ - public void writeField(boolean comma, Attribute attribute); - - public void writeBoolean(boolean value); - - public void writeByte(byte value); - - public void writeChar(char value); - - public void writeShort(short value); - - public void writeInt(int value); - - public void writeLong(long value); - - public void writeFloat(float value); - - public void writeDouble(double value); - - /** - * 写入无转义字符长度不超过255的字符串, 例如枚举值、字段名、类名字符串等 * - * - * @param value - */ - public void writeSmallString(String value); - - public void writeString(String value); -} diff --git a/src/com/wentch/redkale/convert/bson/BsonByteBufferWriter.java b/src/com/wentch/redkale/convert/bson/BsonByteBufferWriter.java deleted file mode 100644 index 8d4a40062..000000000 --- a/src/com/wentch/redkale/convert/bson/BsonByteBufferWriter.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.bson; - -import java.nio.*; -import java.util.function.*; - -/** - * - * @author zhangjx - */ -public final class BsonByteBufferWriter extends BsonWriter { - - private final Supplier supplier; - - private ByteBuffer[] buffers; - - private int index; - - protected BsonByteBufferWriter(Supplier supplier) { - super((byte[]) null); - this.supplier = supplier; - } - - @Override - public ByteBuffer[] toBuffers() { - if (buffers == null) return new ByteBuffer[0]; - for (int i = index; i < this.buffers.length; i++) { - ByteBuffer buf = this.buffers[i]; - if (buf.position() != 0) buf.flip(); - } - return this.buffers; - } - - @Override - public byte[] toArray() { - if (buffers == null) return new byte[0]; - int pos = 0; - byte[] bytes = new byte[this.count]; - for (ByteBuffer buf : toBuffers()) { - int r = buf.remaining(); - buf.get(bytes, pos, r); - buf.flip(); - pos += r; - } - return bytes; - } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "[count=" + this.count + "]"; - } - - @Override - public BsonByteBufferWriter setTiny(boolean tiny) { - this.tiny = tiny; - return this; - } - - @Override - protected int expand(final int byteLength) { - if (this.buffers == null) { - this.index = 0; - this.buffers = new ByteBuffer[]{supplier.get()}; - } - ByteBuffer buffer = this.buffers[index]; - if (!buffer.hasRemaining()) { - buffer.flip(); - buffer = supplier.get(); - ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1]; - System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length); - bufs[this.buffers.length] = buffer; - this.buffers = bufs; - this.index++; - } - int len = buffer.remaining(); - int size = 0; - while (len < byteLength) { - buffer = supplier.get(); - ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1]; - System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length); - bufs[this.buffers.length] = buffer; - this.buffers = bufs; - len += buffer.remaining(); - size++; - } - return size; - } - - @Override - public void writeTo(final byte[] chs, final int start, final int len) { - if (expand(len) == 0) { - this.buffers[index].put(chs, start, len); - } else { - ByteBuffer buffer = this.buffers[index]; - final int end = start + len; - int remain = len; //还剩多少没有写 - while (remain > 0) { - final int br = buffer.remaining(); - if (remain > br) { //一个buffer写不完 - buffer.put(chs, end - remain, br); - buffer = nextByteBuffer(); - remain -= br; - } else { - buffer.put(chs, end - remain, remain); - remain = 0; - } - } - } - this.count += len; - } - - private ByteBuffer nextByteBuffer() { - this.buffers[this.index].flip(); - return this.buffers[++this.index]; - } - - @Override - public void writeTo(final byte ch) { - expand(1); - this.buffers[index].put(ch); - count++; - } - - @Override - protected boolean recycle() { - this.index = 0; - this.buffers = null; - return false; - } -} diff --git a/src/com/wentch/redkale/convert/bson/BsonConvert.java b/src/com/wentch/redkale/convert/bson/BsonConvert.java deleted file mode 100644 index 5fd4c1bb0..000000000 --- a/src/com/wentch/redkale/convert/bson/BsonConvert.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.bson; - -import com.wentch.redkale.convert.*; -import com.wentch.redkale.util.*; -import java.lang.reflect.*; -import java.nio.*; -import java.util.function.*; - -/** - * BSON协议格式: - * 1). 基本数据类型: 直接转换成byte[] - * 2). SmallString(无特殊字符且长度小于256的字符串): length(1 byte) + byte[](utf8); 通常用于类名、字段名、枚举。 - * 3). String: length(4 bytes) + byte[](utf8); - * 4). 数组: length(4 bytes) + byte[]... - * 5). Object: - * 1. realclass (SmallString) (如果指定格式化的class与实体对象的class不一致才会有该值) - * 2. 空字符串(SmallString) - * 3. SIGN_OBJECTB 标记位,值固定为0xBB (short) - * 4. 循环字段值: - * 4.1 SIGN_HASNEXT 标记位,值固定为1 (byte) - * 4.2 字段类型; 1-9为基本类型&字符串; 101-109为基本类型&字符串的数组; 127为Object - * 4.3 字段名 (SmallString) - * 4.4 字段的值Object - * 5. SIGN_NONEXT 标记位,值固定为0 (byte) - * 6. SIGN_OBJECTE 标记位,值固定为0xEE (short) - * - * @author zhangjx - */ -public final class BsonConvert extends Convert { - - private static final ObjectPool readerPool = BsonReader.createPool(Integer.getInteger("convert.bson.pool.size", 16)); - - private static final ObjectPool writerPool = BsonWriter.createPool(Integer.getInteger("convert.bson.pool.size", 16)); - - private final boolean tiny; - - protected BsonConvert(Factory factory, boolean tiny) { - super(factory); - this.tiny = tiny; - } - - public BsonByteBufferWriter pollBsonWriter(final Supplier supplier) { - return new BsonByteBufferWriter(supplier).setTiny(tiny); - } - - public BsonWriter pollBsonWriter() { - return writerPool.get().setTiny(tiny); - } - - public void offerBsonWriter(BsonWriter out) { - if (out != null) writerPool.offer(out); - } - - public BsonReader pollBsonReader() { - return readerPool.get(); - } - - public void offerBsonReader(BsonReader in) { - if (in != null) readerPool.offer(in); - } - - public T convertFrom(final Type type, final byte[] bytes) { - if (bytes == null) return null; - return convertFrom(type, bytes, 0, bytes.length); - } - - public T convertFrom(final Type type, final byte[] bytes, int start, int len) { - if (type == null) return null; - final BsonReader in = readerPool.get(); - in.setBytes(bytes, start, len); - @SuppressWarnings("unchecked") - T rs = (T) factory.loadDecoder(type).convertFrom(in); - readerPool.offer(in); - return rs; - } - - public T convertFrom(final BsonReader in, final Type type) { - if (type == null) return null; - @SuppressWarnings("unchecked") - T rs = (T) factory.loadDecoder(type).convertFrom(in); - return rs; - } - - public byte[] convertTo(final Type type, Object value) { - if (type == null) return null; - final BsonWriter out = writerPool.get().setTiny(tiny); - factory.loadEncoder(type).convertTo(out, value); - byte[] result = out.toArray(); - writerPool.offer(out); - return result; - } - - public void convertTo(final BsonWriter out, final Type type, Object value) { - if (type == null) return; - factory.loadEncoder(type).convertTo(out, value); - } - - public ByteBuffer[] convertTo(final Supplier supplier, final Type type, Object value) { - if (supplier == null || type == null) return null; - BsonByteBufferWriter out = new BsonByteBufferWriter(supplier); - if (value == null) { - out.writeNull(); - } else { - factory.loadEncoder(type).convertTo(out, value); - } - return out.toBuffers(); - } - - public ByteBuffer[] convertTo(final Supplier supplier, Object value) { - if (supplier == null) return null; - BsonByteBufferWriter out = new BsonByteBufferWriter(supplier); - if (value == null) { - out.writeNull(); - } else { - factory.loadEncoder(value.getClass()).convertTo(out, value); - } - return out.toBuffers(); - } - - public void convertTo(final BsonWriter out, Object value) { - if (value == null) { - out.writeNull(); - } else { - factory.loadEncoder(value.getClass()).convertTo(out, value); - } - } - - public byte[] convertTo(Object value) { - if (value == null) { - final BsonWriter out = writerPool.get().setTiny(tiny); - out.writeNull(); - byte[] result = out.toArray(); - writerPool.offer(out); - return result; - } - return convertTo(value.getClass(), value); - } - - public BsonWriter convertToWriter(final Type type, Object value) { - if (type == null) return null; - final BsonWriter out = writerPool.get().setTiny(tiny); - factory.loadEncoder(type).convertTo(out, value); - return out; - } - - public BsonWriter convertToWriter(Object value) { - if (value == null) return null; - return convertToWriter(value.getClass(), value); - } -} diff --git a/src/com/wentch/redkale/convert/bson/BsonFactory.java b/src/com/wentch/redkale/convert/bson/BsonFactory.java deleted file mode 100644 index 8097f6cab..000000000 --- a/src/com/wentch/redkale/convert/bson/BsonFactory.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.bson; - -import com.wentch.redkale.convert.*; -import java.io.Serializable; - -/** - * - * @author zhangjx - */ -public final class BsonFactory extends Factory { - - private static final BsonFactory instance = new BsonFactory(null, Boolean.getBoolean("convert.bson.tiny")); - - static final Decodeable objectDecoder = instance.loadDecoder(Object.class); - - static final Encodeable objectEncoder = instance.loadEncoder(Object.class); - - static { - instance.register(Serializable.class, objectDecoder); - instance.register(Serializable.class, objectEncoder); - } - - private BsonFactory(BsonFactory parent, boolean tiny) { - super(parent, tiny); - } - - public static BsonFactory root() { - return instance; - } - - @Override - public final BsonConvert getConvert() { - if (convert == null) convert = new BsonConvert(this, tiny); - return (BsonConvert) convert; - } - - @Override - public BsonFactory createChild() { - return new BsonFactory(this, this.tiny); - } - - @Override - public BsonFactory createChild(boolean tiny) { - return new BsonFactory(this, tiny); - } - - @Override - public ConvertType getConvertType() { - return ConvertType.BSON; - } - - @Override - public boolean isReversible() { - return true; - } - -} diff --git a/src/com/wentch/redkale/convert/bson/BsonReader.java b/src/com/wentch/redkale/convert/bson/BsonReader.java deleted file mode 100644 index 749fd139d..000000000 --- a/src/com/wentch/redkale/convert/bson/BsonReader.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.bson; - -import com.wentch.redkale.convert.*; -import com.wentch.redkale.convert.ext.*; -import com.wentch.redkale.util.*; -import java.util.concurrent.atomic.*; -import java.util.function.*; - -/** - * - * @author zhangjx - */ -public final class BsonReader implements Reader { - - public static final short SIGN_OBJECTB = (short) 0xBB; - - public static final short SIGN_OBJECTE = (short) 0xEE; - - public static final byte SIGN_HASNEXT = 1; - - public static final byte SIGN_NONEXT = 0; - - public static final byte VERBOSE_NO = 1; - - public static final byte VERBOSE_YES = 2; - - private int position = -1; - - private byte typeval; //字段的类型值 对应 BsonWriter.writeField - - private byte[] content; - - public BsonReader() { - } - - public static ObjectPool createPool(int max) { - return new ObjectPool(max, new Creator() { - - @Override - public BsonReader create(Object... params) { - return new BsonReader(); - } - }, null, new Predicate() { - - @Override - public boolean test(BsonReader t) { - return t.recycle(); - } - }); - } - - public BsonReader(byte[] bytes) { - setBytes(bytes, 0, bytes.length); - } - - public BsonReader(byte[] bytes, int start, int len) { - setBytes(bytes, start, len); - } - - public final void setBytes(byte[] bytes) { - if (bytes == null) { - this.position = 0; - } else { - setBytes(bytes, 0, bytes.length); - } - } - - public final void setBytes(byte[] bytes, int start, int len) { - if (bytes == null) { - this.position = 0; - } else { - this.content = bytes; - this.position = start - 1; - //this.limit = start + len - 1; - } - } - - protected boolean recycle() { - this.position = -1; - this.typeval = 0; - //this.limit = -1; - this.content = null; - return true; - } - - public void close() { - this.recycle(); - } - - /** - * 跳过属性的值 - */ - @Override - public final void skipValue() { - if (typeval == 0) return; - final byte val = this.typeval; - this.typeval = 0; - switch (val) { - case 1: readBoolean(); - break; - case 2: readByte(); - break; - case 3: readShort(); - break; - case 4: readChar(); - break; - case 5: readInt(); - break; - case 6: readLong(); - break; - case 7: readFloat(); - break; - case 8: readDouble(); - break; - case 9: readString(); - break; - case 101: - BoolArraySimpledCoder.instance.convertFrom(this); - break; - case 102: - ByteArraySimpledCoder.instance.convertFrom(this); - break; - case 103: - ShortArraySimpledCoder.instance.convertFrom(this); - break; - case 104: - CharArraySimpledCoder.instance.convertFrom(this); - break; - case 105: - IntArraySimpledCoder.instance.convertFrom(this); - break; - case 106: - LongArraySimpledCoder.instance.convertFrom(this); - break; - case 107: - FloatArraySimpledCoder.instance.convertFrom(this); - break; - case 108: - DoubleArraySimpledCoder.instance.convertFrom(this); - break; - case 109: - StringArraySimpledCoder.instance.convertFrom(this); - break; - case 127: - BsonFactory.objectDecoder.convertFrom(this); - break; - } - } - - /** - * 判断下一个非空白字节是否为{ - * - */ - @Override - public int readObjectB() { - short bt = readShort(); - if (bt == Reader.SIGN_NULL) return bt; - if (bt != SIGN_OBJECTB) { - throw new ConvertException("a bson object must begin with " + (SIGN_OBJECTB) - + " (position = " + position + ") but '" + this.content[this.position] + "'"); - } - return bt; - } - - @Override - public void readObjectE() { - if (readShort() != SIGN_OBJECTE) { - throw new ConvertException("a bson object must end with " + (SIGN_OBJECTE) - + " (position = " + position + ") but '" + this.content[this.position] + "'"); - } - } - - @Override - public int readMapB() { - return readArrayB(); - } - - @Override - public void readMapE() { - } - - /** - * 判断下一个非空白字节是否为[ - * - * @return - */ - @Override - public int readArrayB() { - short bt = readShort(); - if (bt == Reader.SIGN_NULL) return bt; - return (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff); - } - - @Override - public void readArrayE() { - } - - /** - * 判断下一个非空白字节是否: - */ - @Override - public void skipBlank() { - } - - /** - * 判断对象是否存在下一个属性或者数组是否存在下一个元素 - * - * @return - */ - @Override - public boolean hasNext() { - byte b = readByte(); - if (b == SIGN_HASNEXT) return true; - if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT) - + " or " + (SIGN_NONEXT) + ") but '" + b + "' at position(" + this.position + ")"); - return false; - } - - @Override - public DeMember readField(final AtomicInteger index, final DeMember[] members) { - final String exceptedfield = readSmallString(); - this.typeval = readByte(); - final int len = members.length; - int v = index.get(); - if (v >= len) { - v = 0; - index.set(0); - } - for (int k = v; k < len; k++) { - if (exceptedfield.equals(members[k].getAttribute().field())) { - index.set(k); - return members[k]; - } - } - for (int k = 0; k < v; k++) { - if (exceptedfield.equals(members[k].getAttribute().field())) { - index.set(k); - return members[k]; - } - } - return null; - } - - //------------------------------------------------------------ - @Override - public boolean readBoolean() { - return content[++this.position] == 1; - } - - @Override - public byte readByte() { - return content[++this.position]; - } - - @Override - public char readChar() { - return (char) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position])); - } - - @Override - public short readShort() { - return (short) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position])); - } - - @Override - public int readInt() { - return ((content[++this.position] & 0xff) << 24) | ((content[++this.position] & 0xff) << 16) - | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff); - } - - @Override - public long readLong() { - return ((((long) content[++this.position] & 0xff) << 56) - | (((long) content[++this.position] & 0xff) << 48) - | (((long) content[++this.position] & 0xff) << 40) - | (((long) content[++this.position] & 0xff) << 32) - | (((long) content[++this.position] & 0xff) << 24) - | (((long) content[++this.position] & 0xff) << 16) - | (((long) content[++this.position] & 0xff) << 8) - | (((long) content[++this.position] & 0xff))); - } - - @Override - public float readFloat() { - return Float.intBitsToFloat(readInt()); - } - - @Override - public double readDouble() { - return Double.longBitsToDouble(readLong()); - } - - @Override - public String readClassName() { - return readSmallString(); - } - - @Override - public String readSmallString() { - int len = 0xff & readByte(); - if (len == 0) return ""; - String value = new String(content, ++this.position, len); - this.position += len - 1; - return value; - } - - @Override - public String readString() { - int len = readInt(); - if (len == SIGN_NULL) return null; - if (len == 0) return ""; - String value = new String(Utility.decodeUTF8(content, ++this.position, len)); - this.position += len - 1; - return value; - } - -} diff --git a/src/com/wentch/redkale/convert/bson/BsonSimpledCoder.java b/src/com/wentch/redkale/convert/bson/BsonSimpledCoder.java deleted file mode 100644 index 840e1fca3..000000000 --- a/src/com/wentch/redkale/convert/bson/BsonSimpledCoder.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.bson; - -import com.wentch.redkale.convert.SimpledCoder; - -/** - * - * @author zhangjx - * @param - */ -public abstract class BsonSimpledCoder extends SimpledCoder { - -} diff --git a/src/com/wentch/redkale/convert/bson/BsonWriter.java b/src/com/wentch/redkale/convert/bson/BsonWriter.java deleted file mode 100644 index d4c06220c..000000000 --- a/src/com/wentch/redkale/convert/bson/BsonWriter.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.bson; - -import com.wentch.redkale.convert.*; -import com.wentch.redkale.util.*; -import java.nio.*; -import java.util.function.*; - -/** - * - * @author zhangjx - */ -public class BsonWriter implements Writer { - - private static final int defaultSize = Integer.getInteger("convert.bson.writer.buffer.defsize", 1024); - - private byte[] content; - - protected int count; - - protected boolean tiny; - - public static ObjectPool createPool(int max) { - return new ObjectPool(max, new Creator() { - - @Override - public BsonWriter create(Object... params) { - return new BsonWriter(); - } - }, null, new Predicate() { - - @Override - public boolean test(BsonWriter t) { - return t.recycle(); - } - }); - } - - public byte[] toArray() { - if (count == content.length) return content; - byte[] newdata = new byte[count]; - System.arraycopy(content, 0, newdata, 0, count); - return newdata; - } - - public ByteBuffer[] toBuffers() { - return new ByteBuffer[]{ByteBuffer.wrap(content, 0, count)}; - } - - protected BsonWriter(byte[] bs) { - this.content = bs; - } - - public BsonWriter() { - this(defaultSize); - } - - public BsonWriter(int size) { - this.content = new byte[size > 128 ? size : 128]; - } - - @Override - public final boolean isTiny() { - return tiny; - } - - public BsonWriter setTiny(boolean tiny) { - this.tiny = tiny; - return this; - } - - //----------------------------------------------------------------------- - //----------------------------------------------------------------------- - /** - * 扩充指定长度的缓冲区 - * - * @param len - * @return - */ - protected int expand(int len) { - int newcount = count + len; - if (newcount <= content.length) return 0; - byte[] newdata = new byte[Math.max(content.length * 3 / 2, newcount)]; - System.arraycopy(content, 0, newdata, 0, count); - this.content = newdata; - return 0; - } - - public void writeTo(final byte ch) { - expand(1); - content[count++] = ch; - } - - public final void writeTo(final byte... chs) { - writeTo(chs, 0, chs.length); - } - - public void writeTo(final byte[] chs, final int start, final int len) { - expand(len); - System.arraycopy(chs, start, content, count, len); - count += len; - } - - protected boolean recycle() { - this.count = 0; - if (this.content.length > defaultSize) { - this.content = new byte[defaultSize]; - } - return true; - } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "[count=" + this.count + "]"; - } - - //------------------------------------------------------------------------ - public final int count() { - return this.count; - } - - @Override - public final void writeBoolean(boolean value) { - writeTo(value ? (byte) 1 : (byte) 0); - } - - @Override - public final void writeByte(byte value) { - writeTo(value); - } - - @Override - public final void writeChar(final char value) { - writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF)); - } - - @Override - public final void writeShort(short value) { - writeTo((byte) (value >> 8), (byte) value); - } - - @Override - public final void writeInt(int value) { - writeTo((byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value); - } - - @Override - public final void writeLong(long value) { - writeTo((byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32), - (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value); - } - - @Override - public final void writeFloat(float value) { - writeInt(Float.floatToIntBits(value)); - } - - @Override - public final void writeDouble(double value) { - writeLong(Double.doubleToLongBits(value)); - } - - @Override - public final void wirteClassName(String clazz) { - writeSmallString(clazz == null ? "" : clazz); - } - - @Override - public final void writeObjectB(int fieldCount, Object obj) { - writeSmallString(""); - writeShort(BsonReader.SIGN_OBJECTB); - } - - @Override - public final void writeObjectE(Object obj) { - writeByte(BsonReader.SIGN_NONEXT); - writeShort(BsonReader.SIGN_OBJECTE); - } - - @Override - public final void writeField(boolean comma, Attribute attribute) { - writeByte(BsonReader.SIGN_HASNEXT); - writeSmallString(attribute.field()); - byte typeval = 127; //字段的类型值 - final Class type = attribute.type(); - if (type == boolean.class || type == Boolean.class) { - typeval = 1; - } else if (type == byte.class || type == Byte.class) { - typeval = 2; - } else if (type == short.class || type == Short.class) { - typeval = 3; - } else if (type == char.class || type == Character.class) { - typeval = 4; - } else if (type == int.class || type == Integer.class) { - typeval = 5; - } else if (type == long.class || type == Long.class) { - typeval = 6; - } else if (type == float.class || type == Float.class) { - typeval = 7; - } else if (type == double.class || type == Double.class) { - typeval = 8; - } else if (type == String.class) { - typeval = 9; - } else if (type == boolean[].class || type == Boolean[].class) { - typeval = 101; - } else if (type == byte[].class || type == Byte[].class) { - typeval = 102; - } else if (type == short[].class || type == Short[].class) { - typeval = 103; - } else if (type == char[].class || type == Character[].class) { - typeval = 104; - } else if (type == int[].class || type == Integer[].class) { - typeval = 105; - } else if (type == long[].class || type == Long[].class) { - typeval = 106; - } else if (type == float[].class || type == Float[].class) { - typeval = 107; - } else if (type == double[].class || type == Double[].class) { - typeval = 108; - } else if (type == String[].class) { - typeval = 109; - } - writeByte(typeval); - } - - /** - * 对于类的字段名、枚举值这些长度一般不超过255且不会出现双字节字符的字符串采用writeSmallString处理, readSmallString用于读取 - * - * @param value - */ - @Override - public final void writeSmallString(String value) { - if (value.isEmpty()) { - writeTo((byte) 0); - return; - } - char[] chars = Utility.charArray(value); - if (chars.length > 255) throw new ConvertException("'" + value + "' has very long length"); - byte[] bytes = new byte[chars.length + 1]; - bytes[0] = (byte) chars.length; - for (int i = 0; i < chars.length; i++) { - if (chars[i] > Byte.MAX_VALUE) throw new ConvertException("'" + value + "' has double-word"); - bytes[i + 1] = (byte) chars[i]; - } - writeTo(bytes); - } - - @Override - public final void writeString(String value) { - if (value == null) { - writeInt(Reader.SIGN_NULL); - return; - } else if (value.isEmpty()) { - writeInt(0); - return; - } - byte[] bytes = Utility.encodeUTF8(value); - writeInt(bytes.length); - writeTo(bytes); - } - - @Override - public final void writeNull() { - writeShort(Reader.SIGN_NULL); - } - - @Override - public final void writeArrayB(int size) { - writeInt(size); - } - - @Override - public final void writeArrayMark() { - } - - @Override - public final void writeArrayE() { - } - - @Override - public void writeMapB(int size) { - writeArrayB(size); - } - - @Override - public final void writeMapMark() { - } - - @Override - public final void writeMapE() { - } - -} diff --git a/src/com/wentch/redkale/convert/ext/BigIntegerSimpledCoder.java b/src/com/wentch/redkale/convert/ext/BigIntegerSimpledCoder.java deleted file mode 100644 index 735e85c3e..000000000 --- a/src/com/wentch/redkale/convert/ext/BigIntegerSimpledCoder.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; -import com.wentch.redkale.convert.Reader; -import java.math.BigInteger; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class BigIntegerSimpledCoder extends SimpledCoder { - - public static final BigIntegerSimpledCoder instance = new BigIntegerSimpledCoder(); - - @Override - public void convertTo(W out, BigInteger value) { - if (value == null) { - out.writeNull(); - return; - } - ByteArraySimpledCoder.instance.convertTo(out, value.toByteArray()); - } - - @Override - public BigInteger convertFrom(R in) { - byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in); - return bytes == null ? null : new BigInteger(bytes); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/BoolArraySimpledCoder.java b/src/com/wentch/redkale/convert/ext/BoolArraySimpledCoder.java deleted file mode 100644 index 696386202..000000000 --- a/src/com/wentch/redkale/convert/ext/BoolArraySimpledCoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class BoolArraySimpledCoder extends SimpledCoder { - - public static final BoolArraySimpledCoder instance = new BoolArraySimpledCoder(); - - @Override - public void convertTo(W out, boolean[] values) { - if (values == null) { - out.writeNull(); - return; - } - out.writeArrayB(values.length); - boolean flag = false; - for (boolean v : values) { - if (flag) out.writeArrayMark(); - out.writeBoolean(v); - flag = true; - } - out.writeArrayE(); - } - - @Override - public boolean[] convertFrom(R in) { - int len = in.readArrayB(); - if (len == Reader.SIGN_NULL) { - return null; - } else if (len == Reader.SIGN_NOLENGTH) { - int size = 0; - boolean[] data = new boolean[8]; - while (in.hasNext()) { - if (size >= data.length) { - boolean[] newdata = new boolean[data.length + 4]; - System.arraycopy(data, 0, newdata, 0, size); - data = newdata; - } - data[size++] = in.readBoolean(); - } - in.readArrayE(); - boolean[] newdata = new boolean[size]; - System.arraycopy(data, 0, newdata, 0, size); - return newdata; - } else { - boolean[] values = new boolean[len]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readBoolean(); - } - in.readArrayE(); - return values; - } - } - -} diff --git a/src/com/wentch/redkale/convert/ext/BoolSimpledCoder.java b/src/com/wentch/redkale/convert/ext/BoolSimpledCoder.java deleted file mode 100644 index 4b13eb923..000000000 --- a/src/com/wentch/redkale/convert/ext/BoolSimpledCoder.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class BoolSimpledCoder extends SimpledCoder { - - public static final BoolSimpledCoder instance = new BoolSimpledCoder(); - - @Override - public void convertTo(W out, Boolean value) { - out.writeBoolean(value); - } - - @Override - public Boolean convertFrom(R in) { - return in.readBoolean(); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/ByteArraySimpledCoder.java b/src/com/wentch/redkale/convert/ext/ByteArraySimpledCoder.java deleted file mode 100644 index ffd09ccce..000000000 --- a/src/com/wentch/redkale/convert/ext/ByteArraySimpledCoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class ByteArraySimpledCoder extends SimpledCoder { - - public static final ByteArraySimpledCoder instance = new ByteArraySimpledCoder(); - - @Override - public void convertTo(W out, byte[] values) { - if (values == null) { - out.writeNull(); - return; - } - out.writeArrayB(values.length); - boolean flag = false; - for (byte v : values) { - if (flag) out.writeArrayMark(); - out.writeByte(v); - flag = true; - } - out.writeArrayE(); - } - - @Override - public byte[] convertFrom(R in) { - int len = in.readArrayB(); - if (len == Reader.SIGN_NULL) { - return null; - } else if (len == Reader.SIGN_NOLENGTH) { - int size = 0; - byte[] data = new byte[8]; - while (in.hasNext()) { - if (size >= data.length) { - byte[] newdata = new byte[data.length + 4]; - System.arraycopy(data, 0, newdata, 0, size); - data = newdata; - } - data[size++] = in.readByte(); - } - in.readArrayE(); - byte[] newdata = new byte[size]; - System.arraycopy(data, 0, newdata, 0, size); - return newdata; - } else { - byte[] values = new byte[len]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readByte(); - } - in.readArrayE(); - return values; - } - } - -} diff --git a/src/com/wentch/redkale/convert/ext/ByteSimpledCoder.java b/src/com/wentch/redkale/convert/ext/ByteSimpledCoder.java deleted file mode 100644 index e76a6e84c..000000000 --- a/src/com/wentch/redkale/convert/ext/ByteSimpledCoder.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class ByteSimpledCoder extends SimpledCoder { - - public static final ByteSimpledCoder instance = new ByteSimpledCoder(); - - @Override - public void convertTo(W out, Byte value) { - out.writeByte(value); - } - - @Override - public Byte convertFrom(R in) { - return in.readByte(); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/CharArraySimpledCoder.java b/src/com/wentch/redkale/convert/ext/CharArraySimpledCoder.java deleted file mode 100644 index 9b5be5edb..000000000 --- a/src/com/wentch/redkale/convert/ext/CharArraySimpledCoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class CharArraySimpledCoder extends SimpledCoder { - - public static final CharArraySimpledCoder instance = new CharArraySimpledCoder(); - - @Override - public void convertTo(W out, char[] values) { - if (values == null) { - out.writeNull(); - return; - } - out.writeArrayB(values.length); - boolean flag = false; - for (char v : values) { - if (flag) out.writeArrayMark(); - out.writeChar(v); - flag = true; - } - out.writeArrayE(); - } - - @Override - public char[] convertFrom(R in) { - int len = in.readArrayB(); - if (len == Reader.SIGN_NULL) { - return null; - } else if (len == Reader.SIGN_NOLENGTH) { - int size = 0; - char[] data = new char[8]; - while (in.hasNext()) { - if (size >= data.length) { - char[] newdata = new char[data.length + 4]; - System.arraycopy(data, 0, newdata, 0, size); - data = newdata; - } - data[size++] = in.readChar(); - } - in.readArrayE(); - char[] newdata = new char[size]; - System.arraycopy(data, 0, newdata, 0, size); - return newdata; - } else { - char[] values = new char[len]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readChar(); - } - in.readArrayE(); - return values; - } - } - -} diff --git a/src/com/wentch/redkale/convert/ext/CharSimpledCoder.java b/src/com/wentch/redkale/convert/ext/CharSimpledCoder.java deleted file mode 100644 index 26b501043..000000000 --- a/src/com/wentch/redkale/convert/ext/CharSimpledCoder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class CharSimpledCoder extends SimpledCoder { - - public static final CharSimpledCoder instance = new CharSimpledCoder(); - - @Override - public void convertTo(W out, Character value) { - out.writeChar(value); - } - - @Override - public Character convertFrom(R in) { - return in.readChar(); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/DLongSimpledCoder.java b/src/com/wentch/redkale/convert/ext/DLongSimpledCoder.java deleted file mode 100644 index b6fce842a..000000000 --- a/src/com/wentch/redkale/convert/ext/DLongSimpledCoder.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.Writer; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.util.DLong; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class DLongSimpledCoder extends SimpledCoder { - - public static final DLongSimpledCoder instance = new DLongSimpledCoder(); - - @Override - public void convertTo(final W out, final DLong value) { - if (value == null) { - out.writeNull(); - } else { - out.writeSmallString(value.getFirst() + "_" + value.getSecond()); - } - } - - @Override - public DLong convertFrom(R in) { - String str = in.readString(); - if (str == null) return null; - int pos = str.indexOf('_'); - return new DLong(Long.parseLong(str.substring(0, pos)), Long.parseLong(str.substring(pos + 1))); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/DateSimpledCoder.java b/src/com/wentch/redkale/convert/ext/DateSimpledCoder.java deleted file mode 100644 index 4df76df2f..000000000 --- a/src/com/wentch/redkale/convert/ext/DateSimpledCoder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; -import java.util.Date; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class DateSimpledCoder extends SimpledCoder { - - public static final DateSimpledCoder instance = new DateSimpledCoder(); - - @Override - public void convertTo(W out, Date value) { - out.writeLong(value.getTime()); - } - - @Override - public Date convertFrom(R in) { - return new Date(in.readLong()); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/DoubleArraySimpledCoder.java b/src/com/wentch/redkale/convert/ext/DoubleArraySimpledCoder.java deleted file mode 100644 index 04aa3a543..000000000 --- a/src/com/wentch/redkale/convert/ext/DoubleArraySimpledCoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class DoubleArraySimpledCoder extends SimpledCoder { - - public static final DoubleArraySimpledCoder instance = new DoubleArraySimpledCoder(); - - @Override - public void convertTo(W out, double[] values) { - if (values == null) { - out.writeNull(); - return; - } - out.writeArrayB(values.length); - boolean flag = false; - for (double v : values) { - if (flag) out.writeArrayMark(); - out.writeDouble(v); - flag = true; - } - out.writeArrayE(); - } - - @Override - public double[] convertFrom(R in) { - int len = in.readArrayB(); - if (len == Reader.SIGN_NULL) { - return null; - } else if (len == Reader.SIGN_NOLENGTH) { - int size = 0; - double[] data = new double[8]; - while (in.hasNext()) { - if (size >= data.length) { - double[] newdata = new double[data.length + 4]; - System.arraycopy(data, 0, newdata, 0, size); - data = newdata; - } - data[size++] = in.readDouble(); - } - in.readArrayE(); - double[] newdata = new double[size]; - System.arraycopy(data, 0, newdata, 0, size); - return newdata; - } else { - double[] values = new double[len]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readDouble(); - } - in.readArrayE(); - return values; - } - } - -} diff --git a/src/com/wentch/redkale/convert/ext/DoubleSimpledCoder.java b/src/com/wentch/redkale/convert/ext/DoubleSimpledCoder.java deleted file mode 100644 index a56456562..000000000 --- a/src/com/wentch/redkale/convert/ext/DoubleSimpledCoder.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class DoubleSimpledCoder extends SimpledCoder { - - public static final DoubleSimpledCoder instance = new DoubleSimpledCoder(); - - @Override - public void convertTo(W out, Double value) { - out.writeDouble(value); - } - - @Override - public Double convertFrom(R in) { - return in.readDouble(); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/EnumSimpledCoder.java b/src/com/wentch/redkale/convert/ext/EnumSimpledCoder.java deleted file mode 100644 index 323b2b25e..000000000 --- a/src/com/wentch/redkale/convert/ext/EnumSimpledCoder.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - * @param - */ -public final class EnumSimpledCoder extends SimpledCoder { - - private final Class type; - - public EnumSimpledCoder(Class type) { - this.type = type; - } - - @Override - public void convertTo(final W out, final E value) { - if (value == null) { - out.writeNull(); - } else { - out.writeSmallString(value.toString()); - } - } - - @Override - @SuppressWarnings("unchecked") - public E convertFrom(final R in) { - String value = in.readSmallString(); - if (value == null) return null; - return (E) Enum.valueOf(type, value); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/FloatArraySimpledCoder.java b/src/com/wentch/redkale/convert/ext/FloatArraySimpledCoder.java deleted file mode 100644 index ccba72bae..000000000 --- a/src/com/wentch/redkale/convert/ext/FloatArraySimpledCoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class FloatArraySimpledCoder extends SimpledCoder { - - public static final FloatArraySimpledCoder instance = new FloatArraySimpledCoder(); - - @Override - public void convertTo(W out, float[] values) { - if (values == null) { - out.writeNull(); - return; - } - out.writeArrayB(values.length); - boolean flag = false; - for (float v : values) { - if (flag) out.writeArrayMark(); - out.writeFloat(v); - flag = true; - } - out.writeArrayE(); - } - - @Override - public float[] convertFrom(R in) { - int len = in.readArrayB(); - if (len == Reader.SIGN_NULL) { - return null; - } else if (len == Reader.SIGN_NOLENGTH) { - int size = 0; - float[] data = new float[8]; - while (in.hasNext()) { - if (size >= data.length) { - float[] newdata = new float[data.length + 4]; - System.arraycopy(data, 0, newdata, 0, size); - data = newdata; - } - data[size++] = in.readFloat(); - } - in.readArrayE(); - float[] newdata = new float[size]; - System.arraycopy(data, 0, newdata, 0, size); - return newdata; - } else { - float[] values = new float[len]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readFloat(); - } - in.readArrayE(); - return values; - } - } - -} diff --git a/src/com/wentch/redkale/convert/ext/FloatSimpledCoder.java b/src/com/wentch/redkale/convert/ext/FloatSimpledCoder.java deleted file mode 100644 index a2b9cbed5..000000000 --- a/src/com/wentch/redkale/convert/ext/FloatSimpledCoder.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class FloatSimpledCoder extends SimpledCoder { - - public static final FloatSimpledCoder instance = new FloatSimpledCoder(); - - @Override - public void convertTo(W out, Float value) { - out.writeFloat(value); - } - - @Override - public Float convertFrom(R in) { - return in.readFloat(); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/InetAddressSimpledCoder.java b/src/com/wentch/redkale/convert/ext/InetAddressSimpledCoder.java deleted file mode 100644 index 92c2050a1..000000000 --- a/src/com/wentch/redkale/convert/ext/InetAddressSimpledCoder.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; -import com.wentch.redkale.convert.Reader; -import java.net.*; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class InetAddressSimpledCoder extends SimpledCoder { - - public static final InetAddressSimpledCoder instance = new InetAddressSimpledCoder(); - - @Override - public void convertTo(W out, InetAddress value) { - if (value == null) { - out.writeNull(); - return; - } - ByteArraySimpledCoder.instance.convertTo(out, value.getAddress()); - } - - @Override - public InetAddress convertFrom(R in) { - byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in); - if (bytes == null) return null; - try { - return InetAddress.getByAddress(bytes); - } catch (Exception ex) { - return null; - } - } - - public final static class InetSocketAddressSimpledCoder extends SimpledCoder { - - public static final InetSocketAddressSimpledCoder instance = new InetSocketAddressSimpledCoder(); - - @Override - public void convertTo(W out, InetSocketAddress value) { - if (value == null) { - out.writeNull(); - return; - } - ByteArraySimpledCoder.instance.convertTo(out, value.getAddress().getAddress()); - out.writeInt(value.getPort()); - } - - @Override - public InetSocketAddress convertFrom(R in) { - byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in); - if (bytes == null) return null; - int port = in.readInt(); - try { - return new InetSocketAddress(InetAddress.getByAddress(bytes), port); - } catch (Exception ex) { - return null; - } - } - - } -} diff --git a/src/com/wentch/redkale/convert/ext/IntArraySimpledCoder.java b/src/com/wentch/redkale/convert/ext/IntArraySimpledCoder.java deleted file mode 100644 index 8a8c9248a..000000000 --- a/src/com/wentch/redkale/convert/ext/IntArraySimpledCoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class IntArraySimpledCoder extends SimpledCoder { - - public static final IntArraySimpledCoder instance = new IntArraySimpledCoder(); - - @Override - public void convertTo(W out, int[] values) { - if (values == null) { - out.writeNull(); - return; - } - out.writeArrayB(values.length); - boolean flag = false; - for (int v : values) { - if (flag) out.writeArrayMark(); - out.writeInt(v); - flag = true; - } - out.writeArrayE(); - } - - @Override - public int[] convertFrom(R in) { - int len = in.readArrayB(); - if (len == Reader.SIGN_NULL) { - return null; - } else if (len == Reader.SIGN_NOLENGTH) { - int size = 0; - int[] data = new int[8]; - while (in.hasNext()) { - if (size >= data.length) { - int[] newdata = new int[data.length + 4]; - System.arraycopy(data, 0, newdata, 0, size); - data = newdata; - } - data[size++] = in.readInt(); - } - in.readArrayE(); - int[] newdata = new int[size]; - System.arraycopy(data, 0, newdata, 0, size); - return newdata; - } else { - int[] values = new int[len]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readInt(); - } - in.readArrayE(); - return values; - } - } - -} diff --git a/src/com/wentch/redkale/convert/ext/IntSimpledCoder.java b/src/com/wentch/redkale/convert/ext/IntSimpledCoder.java deleted file mode 100644 index e67c1d710..000000000 --- a/src/com/wentch/redkale/convert/ext/IntSimpledCoder.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class IntSimpledCoder extends SimpledCoder { - - public static final IntSimpledCoder instance = new IntSimpledCoder(); - - @Override - public void convertTo(W out, Integer value) { - out.writeInt(value); - } - - @Override - public Integer convertFrom(R in) { - return in.readInt(); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/LongArraySimpledCoder.java b/src/com/wentch/redkale/convert/ext/LongArraySimpledCoder.java deleted file mode 100644 index 27b0d1d35..000000000 --- a/src/com/wentch/redkale/convert/ext/LongArraySimpledCoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class LongArraySimpledCoder extends SimpledCoder { - - public static final LongArraySimpledCoder instance = new LongArraySimpledCoder(); - - @Override - public void convertTo(W out, long[] values) { - if (values == null) { - out.writeNull(); - return; - } - out.writeArrayB(values.length); - boolean flag = false; - for (long v : values) { - if (flag) out.writeArrayMark(); - out.writeLong(v); - flag = true; - } - out.writeArrayE(); - } - - @Override - public long[] convertFrom(R in) { - int len = in.readArrayB(); - if (len == Reader.SIGN_NULL) { - return null; - } else if (len == Reader.SIGN_NOLENGTH) { - int size = 0; - long[] data = new long[8]; - while (in.hasNext()) { - if (size >= data.length) { - long[] newdata = new long[data.length + 4]; - System.arraycopy(data, 0, newdata, 0, size); - data = newdata; - } - data[size++] = in.readLong(); - } - in.readArrayE(); - long[] newdata = new long[size]; - System.arraycopy(data, 0, newdata, 0, size); - return newdata; - } else { - long[] values = new long[len]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readLong(); - } - in.readArrayE(); - return values; - } - } - -} diff --git a/src/com/wentch/redkale/convert/ext/LongSimpledCoder.java b/src/com/wentch/redkale/convert/ext/LongSimpledCoder.java deleted file mode 100644 index 203523b0b..000000000 --- a/src/com/wentch/redkale/convert/ext/LongSimpledCoder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class LongSimpledCoder extends SimpledCoder { - - public static final LongSimpledCoder instance = new LongSimpledCoder(); - - @Override - public void convertTo(W out, Long value) { - out.writeLong(value); - } - - @Override - public Long convertFrom(R in) { - return in.readLong(); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/NumberSimpledCoder.java b/src/com/wentch/redkale/convert/ext/NumberSimpledCoder.java deleted file mode 100644 index aa9e369c7..000000000 --- a/src/com/wentch/redkale/convert/ext/NumberSimpledCoder.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class NumberSimpledCoder extends SimpledCoder { - - public static final NumberSimpledCoder instance = new NumberSimpledCoder(); - - @Override - public void convertTo(W out, Number value) { - out.writeLong(value == null ? 0L : value.longValue()); - } - - @Override - public Number convertFrom(R in) { - return in.readLong(); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/PatternSimpledCoder.java b/src/com/wentch/redkale/convert/ext/PatternSimpledCoder.java deleted file mode 100644 index a225ff9cf..000000000 --- a/src/com/wentch/redkale/convert/ext/PatternSimpledCoder.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.*; -import java.util.regex.*; - -/** - * - * @author zhangjx - * @param - * @param - */ -public class PatternSimpledCoder extends SimpledCoder { - - public static final PatternSimpledCoder instance = new PatternSimpledCoder(); - - @Override - public void convertTo(W out, Pattern value) { - if (value == null) { - out.writeNull(); - } else { - out.writeString(value.flags() + "," + value.pattern()); - } - } - - @Override - public Pattern convertFrom(R in) { - String value = in.readString(); - if (value == null) return null; - int pos = value.indexOf(','); - return Pattern.compile(value.substring(pos + 1), Integer.parseInt(value.substring(0, pos))); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/ShortArraySimpledCoder.java b/src/com/wentch/redkale/convert/ext/ShortArraySimpledCoder.java deleted file mode 100644 index 8c73f94e1..000000000 --- a/src/com/wentch/redkale/convert/ext/ShortArraySimpledCoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class ShortArraySimpledCoder extends SimpledCoder { - - public static final ShortArraySimpledCoder instance = new ShortArraySimpledCoder(); - - @Override - public void convertTo(W out, short[] values) { - if (values == null) { - out.writeNull(); - return; - } - out.writeArrayB(values.length); - boolean flag = false; - for (short v : values) { - if (flag) out.writeArrayMark(); - out.writeShort(v); - flag = true; - } - out.writeArrayE(); - } - - @Override - public short[] convertFrom(R in) { - int len = in.readArrayB(); - if (len == Reader.SIGN_NULL) { - return null; - } else if (len == Reader.SIGN_NOLENGTH) { - int size = 0; - short[] data = new short[8]; - while (in.hasNext()) { - if (size >= data.length) { - short[] newdata = new short[data.length + 4]; - System.arraycopy(data, 0, newdata, 0, size); - data = newdata; - } - data[size++] = in.readShort(); - } - in.readArrayE(); - short[] newdata = new short[size]; - System.arraycopy(data, 0, newdata, 0, size); - return newdata; - } else { - short[] values = new short[len]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readShort(); - } - in.readArrayE(); - return values; - } - } - -} diff --git a/src/com/wentch/redkale/convert/ext/ShortSimpledCoder.java b/src/com/wentch/redkale/convert/ext/ShortSimpledCoder.java deleted file mode 100644 index 50c91b1c9..000000000 --- a/src/com/wentch/redkale/convert/ext/ShortSimpledCoder.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class ShortSimpledCoder extends SimpledCoder { - - public static final ShortSimpledCoder instance = new ShortSimpledCoder(); - - @Override - public void convertTo(W out, Short value) { - out.writeShort(value); - } - - @Override - public Short convertFrom(R in) { - return in.readShort(); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/StringArraySimpledCoder.java b/src/com/wentch/redkale/convert/ext/StringArraySimpledCoder.java deleted file mode 100644 index 8cbc06cf7..000000000 --- a/src/com/wentch/redkale/convert/ext/StringArraySimpledCoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class StringArraySimpledCoder extends SimpledCoder { - - public static final StringArraySimpledCoder instance = new StringArraySimpledCoder(); - - @Override - public void convertTo(W out, String[] values) { - if (values == null) { - out.writeNull(); - return; - } - out.writeArrayB(values.length); - boolean flag = false; - for (String v : values) { - if (flag) out.writeArrayMark(); - out.writeString(v); - flag = true; - } - out.writeArrayE(); - } - - @Override - public String[] convertFrom(R in) { - int len = in.readArrayB(); - if (len == Reader.SIGN_NULL) { - return null; - } else if (len == Reader.SIGN_NOLENGTH) { - int size = 0; - String[] data = new String[8]; - while (in.hasNext()) { - if (size >= data.length) { - String[] newdata = new String[data.length + 4]; - System.arraycopy(data, 0, newdata, 0, size); - data = newdata; - } - data[size++] = in.readString(); - } - in.readArrayE(); - String[] newdata = new String[size]; - System.arraycopy(data, 0, newdata, 0, size); - return newdata; - } else { - String[] values = new String[len]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readString(); - } - in.readArrayE(); - return values; - } - } - -} diff --git a/src/com/wentch/redkale/convert/ext/StringSimpledCoder.java b/src/com/wentch/redkale/convert/ext/StringSimpledCoder.java deleted file mode 100644 index aeafee793..000000000 --- a/src/com/wentch/redkale/convert/ext/StringSimpledCoder.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.SimpledCoder; -import com.wentch.redkale.convert.Writer; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class StringSimpledCoder extends SimpledCoder { - - public static final StringSimpledCoder instance = new StringSimpledCoder(); - - @Override - public void convertTo(W out, String value) { - out.writeString(value); - } - - @Override - public String convertFrom(R in) { - return in.readString(); - } - -} diff --git a/src/com/wentch/redkale/convert/ext/TypeSimpledCoder.java b/src/com/wentch/redkale/convert/ext/TypeSimpledCoder.java deleted file mode 100644 index dc6397252..000000000 --- a/src/com/wentch/redkale/convert/ext/TypeSimpledCoder.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.ext; - -import com.wentch.redkale.convert.Reader; -import com.wentch.redkale.convert.Writer; -import com.wentch.redkale.convert.SimpledCoder; - -/** - * - * @author zhangjx - * @param - * @param - */ -public class TypeSimpledCoder extends SimpledCoder { - - public static final TypeSimpledCoder instance = new TypeSimpledCoder(); - - @Override - public void convertTo(final W out, final Class value) { - if (value == null) { - out.writeNull(); - } else { - out.writeSmallString(value.getName()); - } - } - - @Override - public Class convertFrom(R in) { - String str = in.readSmallString(); - if (str == null) return null; - try { - return Class.forName(str); - } catch (Exception e) { - return null; - } - } - -} diff --git a/src/com/wentch/redkale/convert/json/InetAddressJsonSimpledCoder.java b/src/com/wentch/redkale/convert/json/InetAddressJsonSimpledCoder.java deleted file mode 100644 index 0e0e95eb8..000000000 --- a/src/com/wentch/redkale/convert/json/InetAddressJsonSimpledCoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.json; - -import com.wentch.redkale.convert.*; -import com.wentch.redkale.convert.ext.*; -import java.net.*; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class InetAddressJsonSimpledCoder extends SimpledCoder { - - public static final InetAddressJsonSimpledCoder instance = new InetAddressJsonSimpledCoder(); - - @Override - public void convertTo(JsonWriter out, InetAddress value) { - if (value == null) { - out.writeNull(); - return; - } - StringSimpledCoder.instance.convertTo(out, value.getHostAddress()); - } - - @Override - public InetAddress convertFrom(JsonReader in) { - String str = StringSimpledCoder.instance.convertFrom(in); - if (str == null) return null; - try { - return InetAddress.getByName(str); - } catch (Exception ex) { - return null; - } - } - - public final static class InetSocketAddressJsonSimpledCoder extends SimpledCoder { - - public static final InetSocketAddressJsonSimpledCoder instance = new InetSocketAddressJsonSimpledCoder(); - - @Override - public void convertTo(JsonWriter out, InetSocketAddress value) { - if (value == null) { - out.writeNull(); - return; - } - StringSimpledCoder.instance.convertTo(out, value.getHostString() + ":" + value.getPort()); - } - - @Override - public InetSocketAddress convertFrom(JsonReader in) { - String str = StringSimpledCoder.instance.convertFrom(in); - if (str == null) return null; - try { - int pos = str.indexOf(':'); - return new InetSocketAddress(str.substring(0, pos), Integer.parseInt(str.substring(pos + 1))); - } catch (Exception ex) { - return null; - } - } - - } -} diff --git a/src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java b/src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java deleted file mode 100644 index 6482e3a0f..000000000 --- a/src/com/wentch/redkale/convert/json/JsonByteBufferWriter.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.json; - -import com.wentch.redkale.util.*; -import java.nio.*; -import java.nio.charset.*; -import java.util.*; -import java.util.function.*; - -/** - * - * @author zhangjx - */ -public final class JsonByteBufferWriter extends JsonWriter { - - private static final Charset UTF8 = Charset.forName("UTF-8"); - - private final Charset charset; - - private final Supplier supplier; - - private ByteBuffer[] buffers; - - private int index; - - protected JsonByteBufferWriter(Supplier supplier) { - this(null, supplier); - } - - protected JsonByteBufferWriter(Charset charset, Supplier supplier) { - this.charset = UTF8.equals(charset) ? null : charset; - this.supplier = supplier; - } - - @Override - public JsonByteBufferWriter setTiny(boolean tiny) { - this.tiny = tiny; - return this; - } - - @Override - protected boolean recycle() { - this.index = 0; - this.buffers = null; - return false; - } - - @Override - public ByteBuffer[] toBuffers() { - if (buffers == null) return new ByteBuffer[0]; - for (int i = index; i < this.buffers.length; i++) { - ByteBuffer buf = this.buffers[i]; - if (buf.position() != 0) buf.flip(); - } - return this.buffers; - } - - @Override - public int count() { - if (this.buffers == null) return 0; - int len = 0; - for (ByteBuffer buffer : buffers) { - len += buffer.remaining(); - } - return len; - } - - private int expand(final int byteLength) { - if (this.buffers == null) { - this.index = 0; - this.buffers = new ByteBuffer[]{supplier.get()}; - } - ByteBuffer buffer = this.buffers[index]; - if (!buffer.hasRemaining()) { - buffer.flip(); - buffer = supplier.get(); - ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1]; - System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length); - bufs[this.buffers.length] = buffer; - this.buffers = bufs; - this.index++; - } - int len = buffer.remaining(); - int size = 0; - while (len < byteLength) { - buffer = supplier.get(); - ByteBuffer[] bufs = new ByteBuffer[this.buffers.length + 1]; - System.arraycopy(this.buffers, 0, bufs, 0, this.buffers.length); - bufs[this.buffers.length] = buffer; - this.buffers = bufs; - len += buffer.remaining(); - size++; - } - return size; - } - - @Override - public void writeTo(final char ch) { - if (ch > Byte.MAX_VALUE) throw new RuntimeException("writeTo char(int.value = " + (int) ch + ") must be less 127"); - expand(1); - this.buffers[index].put((byte) ch); - } - - @Override - public void writeTo(final char[] chs, final int start, final int len) { - writeTo(-1, false, chs, start, len); - } - - private void writeTo(int expandsize, final boolean quote, final char[] chs, final int start, final int len) { - int byteLength = quote ? 2 : 0; - ByteBuffer bb = null; - if (charset == null) { - byteLength += encodeUTF8Length(chs, start, len); - } else { - bb = charset.encode(CharBuffer.wrap(chs, start, len)); - byteLength += bb.remaining(); - } - if (expandsize < 0) expandsize = expand(byteLength); - if (expandsize == 0) { // 只需要一个buffer - final ByteBuffer buffer = this.buffers[index]; - if (quote) buffer.put((byte) '"'); - - if (charset == null) { //UTF-8 - final int limit = start + len; - for (int i = start; i < limit; i++) { - char c = chs[i]; - if (c < 0x80) { - buffer.put((byte) c); - } else if (c < 0x800) { - buffer.put((byte) (0xc0 | (c >> 6))); - buffer.put((byte) (0x80 | (c & 0x3f))); - } else { - buffer.put((byte) (0xe0 | ((c >> 12)))); - buffer.put((byte) (0x80 | ((c >> 6) & 0x3f))); - buffer.put((byte) (0x80 | (c & 0x3f))); - } - } - } else { - buffer.put(bb); - } - - if (quote) buffer.put((byte) '"'); - return; - } - ByteBuffer buffer = this.buffers[index]; - if (quote) { - if (!buffer.hasRemaining()) buffer = nextByteBuffer(); - buffer.put((byte) '"'); - } - if (charset == null) { //UTF-8 - final int limit = start + len; - for (int i = start; i < limit; i++) { - buffer = putChar(buffer, chs[i]); - } - } else { - while (bb.hasRemaining()) { - if (!buffer.hasRemaining()) buffer = nextByteBuffer(); - buffer.put(bb.get()); - } - } - if (quote) { - if (!buffer.hasRemaining()) buffer = nextByteBuffer(); - buffer.put((byte) '"'); - } - } - - private ByteBuffer putChar(ByteBuffer buffer, char c) { - if (c < 0x80) { - if (!buffer.hasRemaining()) buffer = nextByteBuffer(); - buffer.put((byte) c); - } else if (c < 0x800) { - if (!buffer.hasRemaining()) buffer = nextByteBuffer(); - buffer.put((byte) (0xc0 | (c >> 6))); - if (!buffer.hasRemaining()) buffer = nextByteBuffer(); - buffer.put((byte) (0x80 | (c & 0x3f))); - } else { - if (!buffer.hasRemaining()) buffer = nextByteBuffer(); - buffer.put((byte) (0xe0 | ((c >> 12)))); - if (!buffer.hasRemaining()) buffer = nextByteBuffer(); - buffer.put((byte) (0x80 | ((c >> 6) & 0x3f))); - if (!buffer.hasRemaining()) buffer = nextByteBuffer(); - buffer.put((byte) (0x80 | (c & 0x3f))); - } - return buffer; - } - - private ByteBuffer nextByteBuffer() { - this.buffers[this.index].flip(); - return this.buffers[++this.index]; - } - - private static int encodeUTF8Length(final char[] text, final int start, final int len) { - char c; - int size = 0; - final char[] chars = text; - final int limit = start + len; - for (int i = start; i < limit; i++) { - c = chars[i]; - size += (c < 0x80 ? 1 : (c < 0x800 ? 2 : 3)); - } - return size; - } - - private static int encodeEscapeUTF8Length(final char[] text, final int start, final int len) { - char c; - int size = 0; - final char[] chars = text; - final int limit = start + len; - for (int i = start; i < limit; i++) { - c = chars[i]; - switch (c) { - case '\n': size += 2; - break; - case '\r': size += 2; - break; - case '\t': size += 2; - break; - case '\\': size += 2; - break; - case '"': size += 2; - break; - default: - size += (c < 0x80 ? 1 : (c < 0x800 ? 2 : 3)); - break; - } - } - return size; - } - - /** - * 注意: 该String值不能为null且不会进行转义, 只用于不含需要转义字符的字符串,例如enum、double、BigInteger转换的String - * - * @param quote - * @param value - */ - @Override - public void writeTo(final boolean quote, final String value) { - char[] chs = Utility.charArray(value); - writeTo(-1, quote, chs, 0, chs.length); - } - - @Override - public void writeString(String value) { - if (value == null) { - writeNull(); - return; - } - final char[] chs = Utility.charArray(value); - int len = 0; - for (char ch : chs) { - switch (ch) { - case '\n': len += 2; - break; - case '\r': len += 2; - break; - case '\t': len += 2; - break; - case '\\': len += 2; - break; - case '"': len += 2; - break; - default: len++; - break; - } - } - if (len == chs.length) { - writeTo(-1, true, chs, 0, len); - return; - } - int expandsize = -1; - if (this.charset == null) { //UTF-8 - final int byteLength = 2 + encodeEscapeUTF8Length(chs, 0, chs.length); - expandsize = expand(byteLength); - if (expandsize == 0) { // 只需要一个buffer - final ByteBuffer buffer = this.buffers[index]; - buffer.put((byte) '"'); - for (char c : chs) { - switch (c) { - case '\n': buffer.put((byte) '\\').put((byte) 'n'); - break; - case '\r': buffer.put((byte) '\\').put((byte) 'r'); - break; - case '\t': buffer.put((byte) '\\').put((byte) 't'); - break; - case '\\': buffer.put((byte) '\\').put((byte) '\\'); - break; - case '"': buffer.put((byte) '\\').put((byte) '"'); - break; - default: - if (c < 0x80) { - buffer.put((byte) c); - } else if (c < 0x800) { - buffer.put((byte) (0xc0 | (c >> 6))); - buffer.put((byte) (0x80 | (c & 0x3f))); - } else { - buffer.put((byte) (0xe0 | ((c >> 12)))); - buffer.put((byte) (0x80 | ((c >> 6) & 0x3f))); - buffer.put((byte) (0x80 | (c & 0x3f))); - } - break; - } - } - buffer.put((byte) '"'); - return; - } - } - StringBuilder sb = new StringBuilder(len); - for (char ch : chs) { - switch (ch) { - case '\n': sb.append("\\n"); - break; - case '\r': sb.append("\\r"); - break; - case '\t': sb.append("\\t"); - break; - case '\\': sb.append("\\\\"); - break; - case '"': sb.append("\\\""); - break; - default: sb.append(ch); - break; - } - } - char[] cs = Utility.charArray(sb); - writeTo(expandsize, true, cs, 0, sb.length()); - } - - @Override - public void writeField(boolean comma, Attribute attribute) { - if (comma) writeTo(','); - writeTo(true, attribute.field()); - writeTo(':'); - } - - @Override - public void writeSmallString(String value) { - writeTo(false, value); - } - - @Override - public String toString() { - return Objects.toString(this); - } -} diff --git a/src/com/wentch/redkale/convert/json/JsonConvert.java b/src/com/wentch/redkale/convert/json/JsonConvert.java deleted file mode 100644 index 2fd8b709c..000000000 --- a/src/com/wentch/redkale/convert/json/JsonConvert.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.json; - -import com.wentch.redkale.convert.*; -import com.wentch.redkale.util.*; -import java.lang.reflect.*; -import java.nio.*; -import java.nio.charset.*; -import java.util.function.*; - -/** - * - * @author zhangjx - */ -@SuppressWarnings("unchecked") -public final class JsonConvert extends Convert { - - public static final Type TYPE_MAP_STRING_STRING = new TypeToken>() { - }.getType(); - - private static final ObjectPool readerPool = JsonReader.createPool(Integer.getInteger("convert.json.pool.size", 16)); - - private static final ObjectPool writerPool = JsonWriter.createPool(Integer.getInteger("convert.json.pool.size", 16)); - - private final boolean tiny; - - protected JsonConvert(JsonFactory factory, boolean tiny) { - super(factory); - this.tiny = tiny; - } - - public JsonByteBufferWriter pollJsonWriter(final Supplier supplier) { - return new JsonByteBufferWriter(supplier).setTiny(tiny); - } - - public JsonByteBufferWriter pollJsonWriter(final Charset charset, final Supplier supplier) { - return new JsonByteBufferWriter(charset, supplier).setTiny(tiny); - } - - public JsonWriter pollJsonWriter() { - return writerPool.get().setTiny(tiny); - } - - public void offerJsonWriter(JsonWriter out) { - if (out != null) writerPool.offer(out); - } - - @Override - public JsonFactory getFactory() { - return (JsonFactory) factory; - } - - public T convertFrom(final Type type, final String text) { - if (text == null) return null; - return convertFrom(type, Utility.charArray(text)); - } - - public T convertFrom(final Type type, final char[] text) { - if (text == null) return null; - return convertFrom(type, text, 0, text.length); - } - - public T convertFrom(final Type type, final char[] text, int start, int len) { - if (text == null || type == null) return null; - final JsonReader in = readerPool.get(); - in.setText(text, start, len); - T rs = (T) factory.loadDecoder(type).convertFrom(in); - readerPool.offer(in); - return rs; - } - - public String convertTo(final Type type, Object value) { - if (type == null) return null; - if (value == null) return "null"; - final JsonWriter out = writerPool.get().setTiny(tiny); - factory.loadEncoder(type).convertTo(out, value); - String result = out.toString(); - writerPool.offer(out); - return result; - } - - public String convertTo(Object value) { - if (value == null) return "null"; - return convertTo(value.getClass(), value); - } - - public void convertTo(final JsonWriter out, final Type type, Object value) { - if (type == null) return; - if (value == null) { - out.writeNull(); - } else { - factory.loadEncoder(type).convertTo(out, value); - } - } - - public void convertTo(final JsonWriter out, Object value) { - if (value == null) { - out.writeNull(); - } else { - factory.loadEncoder(value.getClass()).convertTo(out, value); - } - } - - public ByteBuffer[] convertTo(final Supplier supplier, final Type type, Object value) { - return convertTo(null, supplier, type, value); - } - - public ByteBuffer[] convertTo(final Charset charset, final Supplier supplier, final Type type, Object value) { - if (supplier == null || type == null) return null; - JsonByteBufferWriter out = new JsonByteBufferWriter(charset, supplier); - if (value == null) { - out.writeNull(); - } else { - factory.loadEncoder(type).convertTo(out, value); - } - return out.toBuffers(); - } - - public ByteBuffer[] convertTo(final Supplier supplier, Object value) { - return convertTo(null, supplier, value); - } - - public ByteBuffer[] convertTo(final Charset charset, final Supplier supplier, Object value) { - if (supplier == null) return null; - JsonByteBufferWriter out = new JsonByteBufferWriter(charset, supplier); - if (value == null) { - out.writeNull(); - } else { - factory.loadEncoder(value.getClass()).convertTo(out, value); - } - return out.toBuffers(); - } -} diff --git a/src/com/wentch/redkale/convert/json/JsonFactory.java b/src/com/wentch/redkale/convert/json/JsonFactory.java deleted file mode 100644 index 0b7f5c9f7..000000000 --- a/src/com/wentch/redkale/convert/json/JsonFactory.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.json; - -import com.wentch.redkale.convert.ConvertType; -import com.wentch.redkale.convert.Factory; -import java.io.Serializable; -import java.net.*; - -/** - * - * @author zhangjx - */ -public final class JsonFactory extends Factory { - - private static final JsonFactory instance = new JsonFactory(null, Boolean.getBoolean("convert.json.tiny")); - - static { - instance.register(InetAddress.class, InetAddressJsonSimpledCoder.instance); - instance.register(InetSocketAddress.class, InetAddressJsonSimpledCoder.InetSocketAddressJsonSimpledCoder.instance); - instance.register(Serializable.class, instance.loadEncoder(Object.class)); - } - - private JsonFactory(JsonFactory parent, boolean tiny) { - super(parent, tiny); - } - - public static JsonFactory root() { - return instance; - } - - @Override - public final JsonConvert getConvert() { - if (convert == null) convert = new JsonConvert(this, tiny); - return (JsonConvert) convert; - } - - @Override - public JsonFactory createChild() { - return new JsonFactory(this, this.tiny); - } - - @Override - public JsonFactory createChild(boolean tiny) { - return new JsonFactory(this, tiny); - } - - @Override - public ConvertType getConvertType() { - return ConvertType.JSON; - } - - @Override - public boolean isReversible() { - return false; - } -} diff --git a/src/com/wentch/redkale/convert/json/JsonReader.java b/src/com/wentch/redkale/convert/json/JsonReader.java deleted file mode 100644 index 407f50e12..000000000 --- a/src/com/wentch/redkale/convert/json/JsonReader.java +++ /dev/null @@ -1,576 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.json; - -import com.wentch.redkale.convert.*; -import com.wentch.redkale.util.*; -import java.util.concurrent.atomic.*; -import java.util.function.*; - -/** - * - * @author zhangjx - */ -public final class JsonReader implements Reader { - - private int position = -1; - - private char[] text; - - private int limit; - - public static ObjectPool createPool(int max) { - return new ObjectPool(max, new Creator() { //为了兼容 JDK 6 - - @Override - public JsonReader create(Object... params) { - return new JsonReader(); - } - }, null, new Predicate() { - - @Override - public boolean test(JsonReader t) { - return t.recycle(); - } - }); - } - - public JsonReader() { - } - - public JsonReader(String json) { - setText(Utility.charArray(json)); - } - - public JsonReader(char[] text) { - setText(text, 0, text.length); - } - - public JsonReader(char[] text, int start, int len) { - setText(text, start, len); - } - - public final void setText(String text) { - JsonReader.this.setText(Utility.charArray(text)); - } - - public final void setText(char[] text) { - setText(text, 0, text.length); - } - - public final void setText(char[] text, int start, int len) { - this.text = text; - this.position = start - 1; - this.limit = start + len - 1; - } - - protected boolean recycle() { - this.position = -1; - this.limit = -1; - this.text = null; - return true; - } - - public void close() { - this.recycle(); - } - - /** - * 找到指定的属性值 例如: {id : 1, data : { name : 'a', items : [1,2,3]}} seek('data.items') 直接跳转到 [1,2,3]; - * - * @param key - */ - public final void seek(String key) { - if (key == null || key.length() < 1) return; - final String[] keys = key.split("\\."); - nextGoodChar(); //读掉 { [ - for (String key1 : keys) { - while (this.hasNext()) { - String field = this.readSmallString(); - skipBlank(); - if (key1.equals(field)) break; - skipValue(); - } - } - - } - - /** - * 跳过属性的值 - */ - @Override - public final void skipValue() { - final char ch = nextGoodChar(); - if (ch == '"' || ch == '\'') { - backChar(ch); - readString(); - } else if (ch == '{') { - while (hasNext()) { - this.readSmallString(); //读掉field - this.skipBlank(); - this.skipValue(); - } - } else if (ch == '[') { - while (hasNext()) { - this.skipValue(); - } - } else { - char c; - for (;;) { - c = nextChar(); - if (c <= ' ') return; - if (c == '}' || c == ']' || c == ',' || c == ':') { - backChar(c); - return; - } - } - } - } - - /** - * 读取下一个字符, 不跳过空白字符 - * - * @return - */ - protected char nextChar() { - return this.text[++this.position]; - } - - /** - * 跳过空白字符, 返回一个非空白字符 - * - * @return - */ - protected char nextGoodChar() { - char c = nextChar(); - if (c > ' ') return c; - for (;;) { - c = nextChar(); - if (c > ' ') return c; - } - } - - /** - * 回退最后读取的字符 - * - * @param ch - */ - protected void backChar(char ch) { - this.position--; - } - - /** - * 判断下一个非空白字符是否为{ - * - */ - @Override - public int readObjectB() { - char ch = this.text[++this.position]; - if (ch == '{') return SIGN_NOLENGTH; - if (ch <= ' ') { - for (;;) { - ch = this.text[++this.position]; - if (ch > ' ') break; - } - if (ch == '{') return SIGN_NOLENGTH; - } - if (ch == 'n' && text[++position] == 'u' && text[++position] == 'l' && text[++position] == 'l') return SIGN_NULL; - if (ch == 'N' && text[++position] == 'U' && text[++position] == 'L' && text[++position] == 'L') return SIGN_NULL; - throw new ConvertException("a json object text must begin with '{' (position = " + position + ") but '" + ch + "' in (" + new String(this.text) + ")"); - } - - @Override - public void readObjectE() { - } - - /** - * 判断下一个非空白字符是否为{ - * - */ - @Override - public int readMapB() { - return readArrayB(); - } - - @Override - public void readMapE() { - } - - /** - * 判断下一个非空白字符是否为[ - * - * @return - */ - @Override - public int readArrayB() { - char ch = this.text[++this.position]; - if (ch == '[') return SIGN_NOLENGTH; - if (ch == '{') return SIGN_NOLENGTH; - if (ch <= ' ') { - for (;;) { - ch = this.text[++this.position]; - if (ch > ' ') break; - } - if (ch == '[') return SIGN_NOLENGTH; - if (ch == '{') return SIGN_NOLENGTH; - } - if (ch == 'n' && text[++position] == 'u' && text[++position] == 'l' && text[++position] == 'l') return SIGN_NULL; - if (ch == 'N' && text[++position] == 'U' && text[++position] == 'L' && text[++position] == 'L') return SIGN_NULL; - throw new ConvertException("a json array text must begin with '[' (position = " + position + ") but '" + ch + "' in (" + new String(this.text) + ")"); - } - - @Override - public void readArrayE() { - } - - /** - * 判断下一个非空白字符是否: - */ - @Override - public void skipBlank() { - char ch = this.text[++this.position]; - if (ch == ':') return; - if (ch <= ' ') { - for (;;) { - ch = this.text[++this.position]; - if (ch > ' ') break; - } - if (ch == ':') return; - } - throw new ConvertException("'" + new String(text) + "'expected a ':' but '" + ch + "'(position = " + position + ") in (" + new String(this.text) + ")"); - } - - /** - * 判断对象是否存在下一个属性或者数组是否存在下一个元素 - * - * @return - */ - @Override - public boolean hasNext() { - char ch = this.text[++this.position]; - if (ch == ',') return true; - if (ch == '}' || ch == ']') return false; - if (ch <= ' ') { - for (;;) { - ch = this.text[++this.position]; - if (ch > ' ') break; - } - if (ch == ',') return true; - if (ch == '}' || ch == ']') return false; - } - this.position--; - return true; - } - - @Override - public String readClassName() { - return null; - } - - @Override - public String readSmallString() { - final int eof = this.limit; - if (this.position == eof) return null; - final char[] text0 = this.text; - int currpos = this.position; - char ch = text0[++currpos]; - if (ch <= ' ') { - for (;;) { - ch = text0[++currpos]; - if (ch > ' ') break; - } - } - if (ch == '"' || ch == '\'') { - final char quote = ch; - final int start = currpos + 1; - for (;;) { - ch = text0[++currpos]; - if (ch == '\\') { - this.position = currpos - 1; - return readEscapeValue(quote, start); - } else if (ch == quote) { - break; - } - } - this.position = currpos; - char[] chs = new char[currpos - start]; - System.arraycopy(text0, start, chs, 0, chs.length); - return new String(chs); - } else { - int start = currpos; - for (;;) { - if (currpos == eof) break; - ch = text0[++currpos]; - if (ch == ',' || ch == ']' || ch == '}' || ch <= ' ' || ch == ':') break; - } - int len = currpos - start; - if (len < 1) { - this.position = currpos; - return String.valueOf(ch); - } - this.position = currpos - 1; - if (len == 4 && text0[start] == 'n' && text0[start + 1] == 'u' && text0[start + 2] == 'l' && text0[start + 3] == 'l') return null; - return new String(text0, start, len); - } - } - - /** - * 读取一个int - * - * @return - */ - @Override - public final int readInt() { - final char[] text0 = this.text; - final int eof = this.limit; - int currpos = this.position; - char firstchar = text0[++currpos]; - if (firstchar <= ' ') { - for (;;) { - firstchar = text0[++currpos]; - if (firstchar > ' ') break; - } - } - if (firstchar == '"' || firstchar == '\'') { - firstchar = text0[++currpos]; - if (firstchar == '"' || firstchar == '\'') { - this.position = currpos; - return 0; - } - } - int value = 0; - final boolean negative = firstchar == '-'; - if (!negative) { - if (firstchar < '0' || firstchar > '9') throw new NumberFormatException("illegal escape(" + firstchar + ") (position = " + currpos + ") in (" + new String(this.text) + ")"); - value = firstchar - '0'; - } - for (;;) { - if (currpos == eof) break; - char ch = text0[++currpos]; - if (ch >= '0' && ch <= '9') { - value = (value << 3) + (value << 1) + (ch - '0'); - } else if (ch == '"' || ch == '\'') { - } else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') { - break; - } else { - throw new NumberFormatException("illegal escape(" + ch + ") (position = " + currpos + ") in (" + new String(this.text) + ")"); - } - } - this.position = currpos - 1; - return negative ? -value : value; - } - - /** - * 读取一个long - * - * @return - */ - @Override - public final long readLong() { - final char[] text0 = this.text; - final int eof = this.limit; - int currpos = this.position; - char firstchar = text0[++currpos]; - if (firstchar <= ' ') { - for (;;) { - firstchar = text0[++currpos]; - if (firstchar > ' ') break; - } - } - if (firstchar == '"' || firstchar == '\'') { - firstchar = text0[++currpos]; - if (firstchar == '"' || firstchar == '\'') { - this.position = currpos; - return 0L; - } - } - long value = 0; - final boolean negative = firstchar == '-'; - if (!negative) { - if (firstchar < '0' || firstchar > '9') throw new NumberFormatException("illegal escape(" + firstchar + ") (position = " + currpos + ") in (" + new String(this.text) + ")"); - value = firstchar - '0'; - } - for (;;) { - if (currpos == eof) break; - char ch = text0[++currpos]; - if (ch >= '0' && ch <= '9') { - value = (value << 3) + (value << 1) + (ch - '0'); - } else if (ch == '"' || ch == '\'') { - } else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') { - break; - } else { - throw new NumberFormatException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")"); - } - } - this.position = currpos - 1; - return negative ? -value : value; - } - - @Override - public DeMember readField(final AtomicInteger index, final DeMember[] members) { - final String exceptedfield = this.readSmallString(); - final int len = members.length; - int v = index.get(); - if (v >= len) { - v = 0; - index.set(0); - } - for (int k = v; k < len; k++) { - if (exceptedfield.equals(members[k].getAttribute().field())) { - index.set(k); - return members[k]; - } - } - for (int k = 0; k < v; k++) { - if (exceptedfield.equals(members[k].getAttribute().field())) { - index.set(k); - return members[k]; - } - } - return null; - //if (result == null && len == 1 && text0[start] == '@') return REFER; - } -//------------------------------------------------------------ - - @Override - public boolean readBoolean() { - return "true".equalsIgnoreCase(this.readSmallString()); - } - - @Override - public byte readByte() { - return (byte) readInt(); - } - - @Override - public char readChar() { - return (char) readInt(); - } - - @Override - public short readShort() { - return (short) readInt(); - } - - @Override - public float readFloat() { - String chars = readSmallString(); - if (chars == null || chars.isEmpty()) return 0.f; - return Float.parseFloat(chars); - } - - @Override - public double readDouble() { - String chars = readSmallString(); - if (chars == null || chars.isEmpty()) return 0.0; - return Double.parseDouble(chars); - } - - /** - * 读取字符串, 必须是"或者'包围的字符串值 - * - * @return - */ - @Override - public String readString() { - final char[] text0 = this.text; - int currpos = this.position; - char expected = text0[++currpos]; - if (expected <= ' ') { - for (;;) { - expected = text0[++currpos]; - if (expected > ' ') break; - } - } - if (expected != '"' && expected != '\'') { - if (expected == 'n' && text0.length > currpos + 3) { - if (text0[++currpos] == 'u' && text0[++currpos] == 'l' && text0[++currpos] == 'l') { - this.position = currpos; - if (text0.length > currpos + 4) { - char ch = text0[currpos + 1]; - if (ch == ',' || ch <= ' ' || ch == '}' || ch == ']' || ch == ':') return null; - } else { - return null; - } - } - } else { - final int start = currpos; - for (;;) { - char ch = text0[currpos]; - if (ch == ',' || ch <= ' ' || ch == '}' || ch == ']' || ch == ':') break; - currpos++; - } - if (currpos == start) throw new ConvertException("expected a string after a key but '" + text0[position] + "' (position = " + position + ") in (" + new String(this.text) + ")"); - this.position = currpos - 1; - return new String(text0, start, currpos - start); - } - this.position = currpos; - throw new ConvertException("expected a ':' after a key but '" + text0[position] + "' (position = " + position + ") in (" + new String(this.text) + ")"); - } - final int start = ++currpos; - for (;;) { - char ch = text0[currpos]; - if (ch == expected) { - break; - } else if (ch == '\\') { - this.position = currpos - 1; - return readEscapeValue(expected, start); - } - currpos++; - } - this.position = currpos; - return new String(text0, start, currpos - start); - } - - private String readEscapeValue(final char expected, int start) { - StringBuilder array = new StringBuilder(); - final char[] text0 = this.text; - int pos = this.position; - array.append(text0, start, pos + 1 - start); - char c; - for (;;) { - c = text0[++pos]; - if (c == expected) { - this.position = pos; - return array.toString(); - } else if (c == '\\') { - c = text0[++pos]; - switch (c) { - case '"': - case '\'': - case '\\': - case '/': - array.append(c); - break; - case 'n': - array.append('\n'); - break; - case 'r': - array.append('\r'); - break; - case 'u': - array.append((char) Integer.parseInt(new String(new char[]{text0[++pos], text0[++pos], text0[++pos], text0[++pos]}), 16)); - break; - case 't': - array.append('\t'); - break; - case 'b': - array.append('\b'); - break; - case 'f': - array.append('\f'); - break; - default: - this.position = pos; - throw new ConvertException("illegal escape(" + c + ") (position = " + this.position + ") in (" + new String(this.text) + ")"); - } - } else { - array.append(c); - } - } - } - -} diff --git a/src/com/wentch/redkale/convert/json/JsonSimpledCoder.java b/src/com/wentch/redkale/convert/json/JsonSimpledCoder.java deleted file mode 100644 index cd28528ff..000000000 --- a/src/com/wentch/redkale/convert/json/JsonSimpledCoder.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.json; - -import com.wentch.redkale.convert.SimpledCoder; - -/** - * - * @author zhangjx - * @param - */ -public abstract class JsonSimpledCoder extends SimpledCoder { - -} diff --git a/src/com/wentch/redkale/convert/json/JsonWriter.java b/src/com/wentch/redkale/convert/json/JsonWriter.java deleted file mode 100644 index 8c08296e9..000000000 --- a/src/com/wentch/redkale/convert/json/JsonWriter.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.convert.json; - -import com.wentch.redkale.convert.*; -import com.wentch.redkale.util.*; -import java.nio.*; -import java.util.function.*; - -/** - * - * writeTo系列的方法输出的字符不能含特殊字符 - * - * @author zhangjx - */ -public class JsonWriter implements Writer { - - private static final char[] CHARS_TUREVALUE = "true".toCharArray(); - - private static final char[] CHARS_FALSEVALUE = "false".toCharArray(); - - private static final int defaultSize = Integer.getInteger("convert.json.writer.buffer.defsize", 1024); - - private int count; - - private char[] content; - - protected boolean tiny; - - public static ObjectPool createPool(int max) { - return new ObjectPool(max, new Creator() { - - @Override - public JsonWriter create(Object... params) { - return new JsonWriter(); - } - }, null, new Predicate() { - - @Override - public boolean test(JsonWriter t) { - return t.recycle(); - } - }); - } - - public JsonWriter() { - this(defaultSize); - } - - public JsonWriter(int size) { - this.content = new char[size > 128 ? size : 128]; - } - - @Override - public boolean isTiny() { - return tiny; - } - - public JsonWriter setTiny(boolean tiny) { - this.tiny = tiny; - return this; - } - - //----------------------------------------------------------------------- - //----------------------------------------------------------------------- - /** - * 返回指定至少指定长度的缓冲区 - * - * @param len - * @return - */ - private char[] expand(int len) { - int newcount = count + len; - if (newcount <= content.length) return content; - char[] newdata = new char[Math.max(content.length * 3 / 2, newcount)]; - System.arraycopy(content, 0, newdata, 0, count); - this.content = newdata; - return newdata; - } - - public void writeTo(final char ch) { //只能是 0 - 127 的字符 - expand(1); - content[count++] = ch; - } - - public void writeTo(final char[] chs, final int start, final int len) { //只能是 0 - 127 的字符 - expand(len); - System.arraycopy(chs, start, content, count, len); - count += len; - } - - /** - * 注意: 该String值不能为null且不会进行转义, 只用于不含需要转义字符的字符串,例如enum、double、BigInteger转换的String - * - * @param quote - * @param value - */ - public void writeTo(final boolean quote, final String value) { - int len = value.length(); - expand(len + (quote ? 2 : 0)); - if (quote) content[count++] = '"'; - value.getChars(0, len, content, count); - count += len; - if (quote) content[count++] = '"'; - } - - protected boolean recycle() { - this.count = 0; - if (this.content.length > defaultSize) { - this.content = new char[defaultSize]; - } - return true; - } - - public ByteBuffer[] toBuffers() { - return new ByteBuffer[]{ByteBuffer.wrap(Utility.encodeUTF8(content, 0, count))}; - } - - public int count() { - return this.count; - } - - @Override - public void writeString(String value) { - if (value == null) { - writeNull(); - return; - } - expand(value.length() * 2 + 2); - content[count++] = '"'; - for (char ch : Utility.charArray(value)) { - switch (ch) { - case '\n': content[count++] = '\\'; - content[count++] = 'n'; - break; - case '\r': content[count++] = '\\'; - content[count++] = 'r'; - break; - case '\t': content[count++] = '\\'; - content[count++] = 't'; - break; - case '\\': content[count++] = '\\'; - content[count++] = ch; - break; - case '"': content[count++] = '\\'; - content[count++] = ch; - break; - default: content[count++] = ch; - break; - } - } - content[count++] = '"'; - } - - @Override - public void writeField(boolean comma, Attribute attribute) { - if (comma) writeTo(','); - writeTo(true, attribute.field()); - writeTo(':'); - } - - @Override - public void writeSmallString(String value) { - writeTo(false, value); - } - - @Override - public String toString() { - return new String(content, 0, count); - } - - //---------------------------------------------------------------------------------------------- - public final void writeTo(final char... chs) { //只能是 0 - 127 的字符 - writeTo(chs, 0, chs.length); - } - - @Override - public final void writeBoolean(boolean value) { - writeTo(value ? CHARS_TUREVALUE : CHARS_FALSEVALUE); - } - - @Override - public final void writeByte(byte value) { - writeInt(value); - } - - @Override - public final void writeChar(char value) { - writeInt(value); - } - - @Override - public final void writeShort(short value) { - writeInt(value); - } - - @Override - public final void writeInt(int value) { - writeSmallString(String.valueOf(value)); - } - - @Override - public final void writeLong(long value) { - writeSmallString(String.valueOf(value)); - } - - @Override - public final void writeFloat(float value) { - writeSmallString(String.valueOf(value)); - } - - @Override - public final void writeDouble(double value) { - writeSmallString(String.valueOf(value)); - } - - @Override - public final void wirteClassName(String clazz) { - } - - @Override - public final void writeObjectB(int fieldCount, Object obj) { - writeTo('{'); - } - - @Override - public final void writeObjectE(Object obj) { - writeTo('}'); - } - - @Override - public final void writeNull() { - writeTo('n', 'u', 'l', 'l'); - } - - @Override - public final void writeArrayB(int size) { - writeTo('['); - } - - @Override - public final void writeArrayMark() { - writeTo(','); - } - - @Override - public final void writeArrayE() { - writeTo(']'); - } - - @Override - public final void writeMapB(int size) { - writeTo('{'); - } - - @Override - public final void writeMapMark() { - writeTo(':'); - } - - @Override - public final void writeMapE() { - writeTo('}'); - } -} diff --git a/src/com/wentch/redkale/net/Async.java b/src/com/wentch/redkale/net/Async.java deleted file mode 100644 index a3539b753..000000000 --- a/src/com/wentch/redkale/net/Async.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * 当Service是Remote模式时, 用该注解标注在方法上可使数据变成异步传输, 该注解只能标注在返回类型为void的public方法上 - * 不再起作用, 屏蔽掉 - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({TYPE, METHOD}) -@Retention(RUNTIME) -@Deprecated -public @interface Async { - -} diff --git a/src/com/wentch/redkale/net/AsyncConnection.java b/src/com/wentch/redkale/net/AsyncConnection.java deleted file mode 100644 index 11a905877..000000000 --- a/src/com/wentch/redkale/net/AsyncConnection.java +++ /dev/null @@ -1,570 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import java.io.*; -import java.net.*; -import java.nio.*; -import java.nio.channels.*; -import java.util.*; -import java.util.concurrent.*; - -/** - * - * @author zhangjx - */ -public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCloseable { - - protected Map attributes; - - public abstract boolean isTCP(); - - public abstract SocketAddress getRemoteAddress(); - - public abstract SocketAddress getLocalAddress(); - - public abstract int getReadTimeoutSecond(); - - public abstract int getWriteTimeoutSecond(); - - public abstract void setReadTimeoutSecond(int readTimeoutSecond); - - public abstract void setWriteTimeoutSecond(int writeTimeoutSecond); - - public final void write(ByteBuffer[] srcs, A attachment, CompletionHandler handler) { - write(srcs, 0, srcs.length, attachment, handler); - } - - protected abstract void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler handler); - - public void dispose() {//同close, 只是去掉throws IOException - try { - this.close(); - } catch (IOException io) { - } - } - - @Override - public void close() throws IOException { - if (attributes == null) return; - try { - for (Object obj : attributes.values()) { - if (obj instanceof AutoCloseable) ((AutoCloseable) obj).close(); - } - } catch (Exception io) { - } - } - - public void setAttribute(String name, Object value) { - if (attributes == null) attributes = new HashMap<>(); - attributes.put(name, value); - } - - @SuppressWarnings("unchecked") - public final T getAttribute(String name) { - return (T) (attributes == null ? null : attributes.get(name)); - } - - public final void removeAttribute(String name) { - if (attributes != null) attributes.remove(name); - } - - public final Map getAttributes() { - return attributes; - } - - public final void clearAttribute() { - if (attributes != null) attributes.clear(); - } - - //------------------------------------------------------------------------------------------------------------------------------ - public static AsyncConnection create(final String protocol, final SocketAddress address) throws IOException { - return create(protocol, address, 0, 0); - } - - /** - * 创建客户端连接 - * - * @param protocol - * @param address - * @param readTimeoutSecond0 - * @param writeTimeoutSecond0 - * @return - * @throws java.io.IOException - */ - public static AsyncConnection create(final String protocol, final SocketAddress address, - final int readTimeoutSecond0, final int writeTimeoutSecond0) throws IOException { - if ("TCP".equalsIgnoreCase(protocol)) { - AsynchronousSocketChannel channel = AsynchronousSocketChannel.open(); - try { - channel.connect(address).get(3, TimeUnit.SECONDS); - } catch (Exception e) { - throw new IOException("AsyncConnection connect " + address, e); - } - return create(channel, address, readTimeoutSecond0, writeTimeoutSecond0); - } else if ("UDP".equalsIgnoreCase(protocol)) { - DatagramChannel channel = DatagramChannel.open(); - channel.configureBlocking(true); - channel.connect(address); - return create(channel, address, true, readTimeoutSecond0, writeTimeoutSecond0); - } else { - throw new RuntimeException("AsyncConnection not support protocol " + protocol); - } - } - - private static class BIOUDPAsyncConnection extends AsyncConnection { - - private int readTimeoutSecond; - - private int writeTimeoutSecond; - - private final DatagramChannel channel; - - private final SocketAddress remoteAddress; - - private final boolean client; - - public BIOUDPAsyncConnection(final DatagramChannel ch, SocketAddress addr, - final boolean client0, final int readTimeoutSecond0, final int writeTimeoutSecond0) { - this.channel = ch; - this.client = client0; - this.readTimeoutSecond = readTimeoutSecond0; - this.writeTimeoutSecond = writeTimeoutSecond0; - this.remoteAddress = addr; - } - - @Override - public void setReadTimeoutSecond(int readTimeoutSecond) { - this.readTimeoutSecond = readTimeoutSecond; - } - - @Override - public void setWriteTimeoutSecond(int writeTimeoutSecond) { - this.writeTimeoutSecond = writeTimeoutSecond; - } - - @Override - public int getReadTimeoutSecond() { - return this.readTimeoutSecond; - } - - @Override - public int getWriteTimeoutSecond() { - return this.writeTimeoutSecond; - } - - @Override - public final SocketAddress getRemoteAddress() { - return remoteAddress; - } - - @Override - public SocketAddress getLocalAddress() { - try { - return channel.getLocalAddress(); - } catch (IOException e) { - return null; - } - } - - @Override - protected void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler handler) { - try { - int rs = 0; - for (int i = offset; i < offset + length; i++) { - rs += channel.send(srcs[i], remoteAddress); - if(i != offset) Thread.sleep(10); - } - if (handler != null) handler.completed(rs, attachment); - } catch (Exception e) { - if (handler != null) handler.failed(e, attachment); - } - } - - @Override - public void read(ByteBuffer dst, A attachment, CompletionHandler handler) { - try { - int rs = channel.read(dst); - if (handler != null) handler.completed(rs, attachment); - } catch (IOException e) { - if (handler != null) handler.failed(e, attachment); - } - } - - @Override - public Future read(ByteBuffer dst) { - try { - int rs = channel.read(dst); - return new SimpleFuture(rs); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void write(ByteBuffer src, A attachment, CompletionHandler handler) { - try { - int rs = channel.send(src, remoteAddress); - if (handler != null) handler.completed(rs, attachment); - } catch (IOException e) { - if (handler != null) handler.failed(e, attachment); - } - } - - @Override - public Future write(ByteBuffer src) { - try { - int rs = channel.send(src, remoteAddress); - return new SimpleFuture(rs); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public final void close() throws IOException { - super.close(); - if (client) { - channel.close(); - } - } - - @Override - public final boolean isOpen() { - return channel.isOpen(); - } - - @Override - public final boolean isTCP() { - return false; - } - } - - public static AsyncConnection create(final DatagramChannel ch, SocketAddress addr, - final boolean client0, final int readTimeoutSecond0, final int writeTimeoutSecond0) { - return new BIOUDPAsyncConnection(ch, addr, client0, readTimeoutSecond0, writeTimeoutSecond0); - } - - private static class SimpleFuture implements Future { - - private final int rs; - - public SimpleFuture(int rs) { - this.rs = rs; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return true; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return true; - } - - @Override - public Integer get() throws InterruptedException, ExecutionException { - return rs; - } - - @Override - public Integer get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - return rs; - } - - } - - private static class BIOTCPAsyncConnection extends AsyncConnection { - - private int readTimeoutSecond; - - private int writeTimeoutSecond; - - private final Socket socket; - - private final ReadableByteChannel readChannel; - - private final WritableByteChannel writeChannel; - - private final SocketAddress remoteAddress; - - public BIOTCPAsyncConnection(final Socket socket, final SocketAddress addr0, final int readTimeoutSecond0, final int writeTimeoutSecond0) { - this.socket = socket; - ReadableByteChannel rc = null; - WritableByteChannel wc = null; - try { - socket.setSoTimeout(Math.max(readTimeoutSecond0, writeTimeoutSecond0)); - rc = Channels.newChannel(socket.getInputStream()); - wc = Channels.newChannel(socket.getOutputStream()); - } catch (IOException e) { - e.printStackTrace(); - } - this.readChannel = rc; - this.writeChannel = wc; - this.readTimeoutSecond = readTimeoutSecond0; - this.writeTimeoutSecond = writeTimeoutSecond0; - SocketAddress addr = addr0; - if (addr == null) { - try { - addr = socket.getRemoteSocketAddress(); - } catch (Exception e) { - //do nothing - } - } - this.remoteAddress = addr; - } - - @Override - public boolean isTCP() { - return true; - } - - @Override - public SocketAddress getRemoteAddress() { - return remoteAddress; - } - - @Override - public SocketAddress getLocalAddress() { - return socket.getLocalSocketAddress(); - } - - @Override - public int getReadTimeoutSecond() { - return readTimeoutSecond; - } - - @Override - public int getWriteTimeoutSecond() { - return writeTimeoutSecond; - } - - @Override - public void setReadTimeoutSecond(int readTimeoutSecond) { - this.readTimeoutSecond = readTimeoutSecond; - } - - @Override - public void setWriteTimeoutSecond(int writeTimeoutSecond) { - this.writeTimeoutSecond = writeTimeoutSecond; - } - - @Override - protected void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler handler) { - try { - int rs = 0; - for (int i = offset; i < offset + length; i++) { - rs += writeChannel.write(srcs[i]); - } - if (handler != null) handler.completed(rs, attachment); - } catch (IOException e) { - if (handler != null) handler.failed(e, attachment); - } - } - - @Override - public void read(ByteBuffer dst, A attachment, CompletionHandler handler) { - try { - int rs = readChannel.read(dst); - if (handler != null) handler.completed(rs, attachment); - } catch (IOException e) { - if (handler != null) handler.failed(e, attachment); - } - } - - @Override - public Future read(ByteBuffer dst) { - try { - int rs = readChannel.read(dst); - return new SimpleFuture(rs); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void write(ByteBuffer src, A attachment, CompletionHandler handler) { - try { - int rs = writeChannel.write(src); - if (handler != null) handler.completed(rs, attachment); - } catch (IOException e) { - if (handler != null) handler.failed(e, attachment); - } - } - - @Override - public Future write(ByteBuffer src) { - try { - int rs = writeChannel.write(src); - return new SimpleFuture(rs); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void close() throws IOException { - super.close(); - this.socket.close(); - } - - @Override - public boolean isOpen() { - return !socket.isClosed(); - } - } - - /** - * 通常用于 ssl socket - * @param socket - * @return - */ - public static AsyncConnection create(final Socket socket) { - return create(socket, null, 0, 0); - } - - public static AsyncConnection create(final Socket socket, final SocketAddress addr0, final int readTimeoutSecond0, final int writeTimeoutSecond0) { - return new BIOTCPAsyncConnection(socket, addr0, readTimeoutSecond0, writeTimeoutSecond0); - } - - private static class AIOTCPAsyncConnection extends AsyncConnection { - - private int readTimeoutSecond; - - private int writeTimeoutSecond; - - private final AsynchronousSocketChannel channel; - - private final SocketAddress remoteAddress; - - public AIOTCPAsyncConnection(final AsynchronousSocketChannel ch, final SocketAddress addr0, final int readTimeoutSecond0, final int writeTimeoutSecond0) { - this.channel = ch; - this.readTimeoutSecond = readTimeoutSecond0; - this.writeTimeoutSecond = writeTimeoutSecond0; - SocketAddress addr = addr0; - if (addr == null) { - try { - addr = ch.getRemoteAddress(); - } catch (Exception e) { - //do nothing - } - } - this.remoteAddress = addr; - } - - @Override - public void read(ByteBuffer dst, A attachment, CompletionHandler handler) { - if (readTimeoutSecond > 0) { - channel.read(dst, readTimeoutSecond, TimeUnit.SECONDS, attachment, handler); - } else { - channel.read(dst, attachment, handler); - } - } - - @Override - public void write(ByteBuffer src, A attachment, CompletionHandler handler) { - if (writeTimeoutSecond > 0) { - channel.write(src, writeTimeoutSecond, TimeUnit.SECONDS, attachment, handler); - } else { - channel.write(src, attachment, handler); - } - } - - @Override - public void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler handler) { - channel.write(srcs, offset, length, writeTimeoutSecond > 0 ? writeTimeoutSecond : 60, TimeUnit.SECONDS, - attachment, new CompletionHandler() { - - @Override - public void completed(Long result, A attachment) { - handler.completed(result.intValue(), attachment); - } - - @Override - public void failed(Throwable exc, A attachment) { - handler.failed(exc, attachment); - } - - }); - } - - @Override - public void setReadTimeoutSecond(int readTimeoutSecond) { - this.readTimeoutSecond = readTimeoutSecond; - } - - @Override - public void setWriteTimeoutSecond(int writeTimeoutSecond) { - this.writeTimeoutSecond = writeTimeoutSecond; - } - - @Override - public int getReadTimeoutSecond() { - return this.readTimeoutSecond; - } - - @Override - public int getWriteTimeoutSecond() { - return this.writeTimeoutSecond; - } - - @Override - public final SocketAddress getRemoteAddress() { - return remoteAddress; - } - - @Override - public SocketAddress getLocalAddress() { - try { - return channel.getLocalAddress(); - } catch (IOException e) { - return null; - } - } - - @Override - public final Future read(ByteBuffer dst) { - return channel.read(dst); - } - - @Override - public final Future write(ByteBuffer src) { - return channel.write(src); - } - - @Override - public final void close() throws IOException { - super.close(); - channel.close(); - } - - @Override - public final boolean isOpen() { - return channel.isOpen(); - } - - @Override - public final boolean isTCP() { - return true; - } - - } - - public static AsyncConnection create(final AsynchronousSocketChannel ch) { - return create(ch, null, 0, 0); - } - - public static AsyncConnection create(final AsynchronousSocketChannel ch, final SocketAddress addr0, final int readTimeoutSecond0, final int writeTimeoutSecond0) { - return new AIOTCPAsyncConnection(ch, addr0, readTimeoutSecond0, writeTimeoutSecond0); - } - -} diff --git a/src/com/wentch/redkale/net/AsyncDatagramChannel.java b/src/com/wentch/redkale/net/AsyncDatagramChannel.java deleted file mode 100644 index 3b28cb1eb..000000000 --- a/src/com/wentch/redkale/net/AsyncDatagramChannel.java +++ /dev/null @@ -1,1327 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import java.io.*; -import java.lang.invoke.*; -import java.lang.ref.*; -import java.lang.reflect.*; -import java.net.*; -import java.nio.*; -import java.nio.channels.*; -import java.security.*; -import java.util.*; -import java.util.concurrent.*; -import sun.misc.*; -import sun.security.action.*; - -/** - * - * @author zhangjx - */ -@SuppressWarnings("unchecked") -public final class AsyncDatagramChannel implements AsynchronousByteChannel, MulticastChannel { - - private final DatagramChannel dc; - - private final AsynchronousChannelGroupProxy group; - - private final Object attachKey; - - private boolean closed; - - // used to coordinate timed and blocking reads - private final Object readLock = new Object(); - - // channel blocking mode (requires readLock) - private boolean isBlocking = true; - - // number of blocking readers (requires readLock) - private int blockingReaderCount; - - // true if timed read attempted while blocking read in progress (requires readLock) - private boolean transitionToNonBlocking; - - // true if a blocking read is cancelled (requires readLock) - private boolean blockingReadKilledByCancel; - - // temporary Selectors used by timed reads (requires readLock) - private Selector firstReader; - - private Set otherReaders; - - private static final sun.misc.Unsafe UNSAFE; - - private static final long fdoffset; - - static { - sun.misc.Unsafe usafe = null; - long fd = 0L; - try { - Field safeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); - safeField.setAccessible(true); - usafe = (sun.misc.Unsafe) safeField.get(null); - fd = usafe.objectFieldOffset(DatagramChannel.open().getClass().getDeclaredField("fd")); - } catch (Exception e) { - throw new RuntimeException(e); - } - UNSAFE = usafe; - fdoffset = fd; - } - - private AsyncDatagramChannel(ProtocolFamily family, AsynchronousChannelGroup group0) - throws IOException { - this.dc = (family == null) ? DatagramChannel.open() : DatagramChannel.open(family); - if (group0 == null) group0 = AsynchronousChannelGroup.withThreadPool(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2)); - this.group = new AsynchronousChannelGroupProxy(group0); - - // attach this channel to the group as foreign channel - boolean registered = false; - try { - attachKey = group.attachForeignChannel(this, (FileDescriptor) UNSAFE.getObject(dc, fdoffset)); - registered = true; - } finally { - if (!registered) - dc.close(); - } - } - - public static AsyncDatagramChannel open(AsynchronousChannelGroup group) throws IOException { - return open(null, group); - } - - public static AsyncDatagramChannel open(ProtocolFamily family, AsynchronousChannelGroup group) - throws IOException { - return new AsyncDatagramChannel(family, group); - } - - @Override - public final void read(ByteBuffer dst, A attachment, CompletionHandler handler) { - read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler); - } - - // throws RuntimeException if blocking read has been cancelled - private void ensureBlockingReadNotKilled() { - assert Thread.holdsLock(readLock); - if (blockingReadKilledByCancel) throw new RuntimeException("Reading not allowed due to cancellation"); - } - - // invoke prior to non-timed read/receive - private void beginNoTimeoutRead() { - synchronized (readLock) { - ensureBlockingReadNotKilled(); - if (isBlocking) blockingReaderCount++; - } - } - - // invoke after non-timed read/receive has completed - private void endNoTimeoutRead() { - synchronized (readLock) { - if (isBlocking) { - if (--blockingReaderCount == 0 && transitionToNonBlocking) { - // notify any threads waiting to make channel non-blocking - readLock.notifyAll(); - } - } - } - } - - // invoke prior to timed read - // returns the timeout remaining - private long prepareForTimedRead(PendingFuture result, long timeout) throws IOException { - synchronized (readLock) { - ensureBlockingReadNotKilled(); - if (isBlocking) { - transitionToNonBlocking = true; - while (blockingReaderCount > 0 && timeout > 0L && !result.isCancelled()) { - long st = System.currentTimeMillis(); - try { - readLock.wait(timeout); - } catch (InterruptedException e) { - } - timeout -= System.currentTimeMillis() - st; - } - if (blockingReaderCount == 0) { - // re-check that blocked read wasn't cancelled - ensureBlockingReadNotKilled(); - // no blocking reads so change channel to non-blocking - dc.configureBlocking(false); - isBlocking = false; - } - } - return timeout; - } - } - - // returns a temporary Selector - private Selector getSelector() throws IOException { - Selector sel = getTemporarySelector(dc); - synchronized (readLock) { - if (firstReader == null) { - firstReader = sel; - } else { - if (otherReaders == null) otherReaders = new HashSet<>(); - otherReaders.add(sel); - } - } - return sel; - } - - // releases a temporary Selector - private void releaseSelector(Selector sel) throws IOException { - synchronized (readLock) { - if (firstReader == sel) { - firstReader = null; - } else { - otherReaders.remove(sel); - } - } - releaseTemporarySelector(sel); - } - - // wakeup all Selectors currently in use - private void wakeupSelectors() { - synchronized (readLock) { - if (firstReader != null) - firstReader.wakeup(); - if (otherReaders != null) { - for (Selector sel : otherReaders) { - sel.wakeup(); - } - } - } - } - - public AsynchronousChannelGroupProxy group() { - return group; - } - - @Override - public boolean isOpen() { - return dc.isOpen(); - } - - public void onCancel(PendingFuture task) { - synchronized (readLock) { - if (blockingReaderCount > 0) { - blockingReadKilledByCancel = true; - readLock.notifyAll(); - return; - } - } - wakeupSelectors(); - } - - @Override - public void close() throws IOException { - synchronized (dc) { - if (closed) return; - closed = true; - } - // detach from group and close underlying channel - group.detachForeignChannel(attachKey); - dc.close(); - - // wakeup any threads blocked in timed read/receives - wakeupSelectors(); - } - - public AsyncDatagramChannel connect(SocketAddress remote) - throws IOException { - dc.connect(remote); - return this; - } - - public AsyncDatagramChannel disconnect() throws IOException { - dc.disconnect(); - return this; - } - - private static class WrappedMembershipKey extends MembershipKey { - - private final MulticastChannel channel; - - private final MembershipKey key; - - WrappedMembershipKey(MulticastChannel channel, MembershipKey key) { - this.channel = channel; - this.key = key; - } - - @Override - public boolean isValid() { - return key.isValid(); - } - - @Override - public void drop() { - key.drop(); - } - - @Override - public MulticastChannel channel() { - return channel; - } - - @Override - public InetAddress group() { - return key.group(); - } - - @Override - public NetworkInterface networkInterface() { - return key.networkInterface(); - } - - @Override - public InetAddress sourceAddress() { - return key.sourceAddress(); - } - - @Override - public MembershipKey block(InetAddress toBlock) throws IOException { - key.block(toBlock); - return this; - } - - @Override - public MembershipKey unblock(InetAddress toUnblock) { - key.unblock(toUnblock); - return this; - } - - @Override - public String toString() { - return key.toString(); - } - } - - @Override - public MembershipKey join(InetAddress group, - NetworkInterface interf) - throws IOException { - MembershipKey key = ((MulticastChannel) dc).join(group, interf); - return new WrappedMembershipKey(this, key); - } - - @Override - public MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source) throws IOException { - MembershipKey key = ((MulticastChannel) dc).join(group, interf, source); - return new WrappedMembershipKey(this, key); - } - - private Future implSend(ByteBuffer src, SocketAddress target, A attachment, CompletionHandler handler) { - int n = 0; - Throwable exc = null; - try { - n = dc.send(src, target); - } catch (IOException ioe) { - exc = ioe; - } - if (handler == null) - return CompletedFuture.withResult(n, exc); - Invoker.invoke(this, handler, attachment, n, exc); - return null; - } - - public Future send(ByteBuffer src, SocketAddress target) { - return implSend(src, target, null, null); - } - - public void send(ByteBuffer src, SocketAddress target, A attachment, CompletionHandler handler) { - if (handler == null) throw new NullPointerException("'handler' is null"); - implSend(src, target, attachment, handler); - } - - public void send(ByteBuffer[] srcs, final int offset, final int length, SocketAddress target, A attachment, final CompletionHandler handler) { - if (handler == null) throw new NullPointerException("'handler' is null"); - final ByteBuffer[] buffers = srcs; - implSend(buffers[offset], target, attachment, new CompletionHandler() { - private int index = offset; - - private int resultSum; - - private final int max = length - 1; - - @Override - public void completed(Integer result, A attachment) { - resultSum += result; - if (buffers[index].hasRemaining()) { - implSend(buffers[index], target, attachment, this); - } else if (index == max) { - if (handler != null) handler.completed(resultSum, attachment); - } else { - implSend(buffers[++index], target, attachment, this); - } - } - - @Override - public void failed(Throwable exc, A attachment) { - if (handler != null) handler.failed(exc, attachment); - } - }); - } - - private Future implWrite(ByteBuffer src, A attachment, CompletionHandler handler) { - int n = 0; - Throwable exc = null; - try { - n = dc.write(src); - } catch (IOException ioe) { - exc = ioe; - } - if (handler == null) return CompletedFuture.withResult(n, exc); - Invoker.invoke(this, handler, attachment, n, exc); - return null; - - } - - @Override - public Future write(ByteBuffer src) { - return implWrite(src, null, null); - } - - @Override - public void write(ByteBuffer src, A attachment, CompletionHandler handler) { - if (handler == null) throw new NullPointerException("'handler' is null"); - implWrite(src, attachment, handler); - } - - /** - * Receive into the given buffer with privileges enabled and restricted by the given AccessControlContext (can be null). - */ - private SocketAddress doRestrictedReceive(final ByteBuffer dst, - AccessControlContext acc) - throws IOException { - if (acc == null) { - return dc.receive(dst); - } else { - try { - return AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public SocketAddress run() throws IOException { - return dc.receive(dst); - } - }, acc); - } catch (PrivilegedActionException pae) { - Exception cause = pae.getException(); - if (cause instanceof SecurityException) - throw (SecurityException) cause; - throw (IOException) cause; - } - } - } - - private Future implReceive(final ByteBuffer dst, final long timeout, - final TimeUnit unit, A attachment, final CompletionHandler handler) { - if (dst.isReadOnly()) throw new IllegalArgumentException("Read-only buffer"); - if (timeout < 0L) throw new IllegalArgumentException("Negative timeout"); - if (unit == null) throw new NullPointerException(); - - // complete immediately if channel closed - if (!isOpen()) { - Throwable exc = new ClosedChannelException(); - if (handler == null) return CompletedFuture.withFailure(exc); - Invoker.invoke(this, handler, attachment, null, exc); - return null; - } - - final AccessControlContext acc = (System.getSecurityManager() == null) ? null : AccessController.getContext(); - final PendingFuture result = new PendingFuture(this, handler, attachment); - Runnable task = new Runnable() { - public void run() { - try { - SocketAddress remote = null; - long to; - if (timeout == 0L) { - beginNoTimeoutRead(); - try { - remote = doRestrictedReceive(dst, acc); - } finally { - endNoTimeoutRead(); - } - to = 0L; - } else { - to = prepareForTimedRead(result, unit.toMillis(timeout)); - if (to <= 0L) throw new InterruptedByTimeoutException(); - remote = doRestrictedReceive(dst, acc); - } - if (remote == null) { - Selector sel = getSelector(); - SelectionKey sk = null; - try { - sk = dc.register(sel, SelectionKey.OP_READ); - for (;;) { - if (!dc.isOpen()) throw new AsynchronousCloseException(); - if (result.isCancelled()) break; - long st = System.currentTimeMillis(); - int ns = sel.select(to); - if (ns > 0) { - remote = doRestrictedReceive(dst, acc); - if (remote != null) break; - } - sel.selectedKeys().remove(sk); - if (timeout != 0L) { - to -= System.currentTimeMillis() - st; - if (to <= 0) throw new InterruptedByTimeoutException(); - } - } - } finally { - if (sk != null) - sk.cancel(); - releaseSelector(sel); - } - } - result.setResult(remote); - } catch (Exception x) { - if (x instanceof ClosedChannelException) - x = new AsynchronousCloseException(); - result.setFailure(x); - } - Invoker.invokeUnchecked(result); - } - }; - try { - group.executeOnPooledThread(task); - } catch (RejectedExecutionException ree) { - throw new ShutdownChannelGroupException(); - } - return result; - } - - public Future receive(ByteBuffer dst) { - return implReceive(dst, 0L, TimeUnit.MILLISECONDS, null, null); - } - - public void receive(ByteBuffer dst, A attachment, CompletionHandler handler) { - receive(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler); - } - - public void receive(ByteBuffer dst, long timeout, TimeUnit unit, A attachment, CompletionHandler handler) { - if (handler == null) throw new NullPointerException("'handler' is null"); - implReceive(dst, timeout, unit, attachment, handler); - } - - private Future implRead(final ByteBuffer dst, long timeout, TimeUnit unit, A attachment, CompletionHandler handler) { - if (dst.isReadOnly()) throw new IllegalArgumentException("Read-only buffer"); - if (timeout < 0L) throw new IllegalArgumentException("Negative timeout"); - if (unit == null) throw new NullPointerException(); - - // complete immediately if channel closed - if (!isOpen()) { - Throwable exc = new ClosedChannelException(); - if (handler == null) return CompletedFuture.withFailure(exc); - Invoker.invoke(this, handler, attachment, null, exc); - return null; - } - - // another thread may disconnect before read is initiated - if (!dc.isConnected()) throw new NotYetConnectedException(); - - final PendingFuture result = new PendingFuture(this, handler, attachment); - Runnable task = new Runnable() { - public void run() { - try { - int n = 0; - long to; - if (timeout == 0L) { - beginNoTimeoutRead(); - try { - n = dc.read(dst); - } finally { - endNoTimeoutRead(); - } - to = 0L; - } else { - to = prepareForTimedRead(result, unit.toMillis(timeout)); - if (to <= 0L) throw new InterruptedByTimeoutException(); - n = dc.read(dst); - } - if (n == 0) { - Selector sel = getSelector(); - SelectionKey sk = null; - try { - sk = dc.register(sel, SelectionKey.OP_READ); - for (;;) { - if (!dc.isOpen()) throw new AsynchronousCloseException(); - if (result.isCancelled()) break; - long st = System.currentTimeMillis(); - int ns = sel.select(to); - if (ns > 0) { - if ((n = dc.read(dst)) != 0) break; - } - sel.selectedKeys().remove(sk); - if (timeout != 0L) { - to -= System.currentTimeMillis() - st; - if (to <= 0) throw new InterruptedByTimeoutException(); - } - } - } finally { - if (sk != null) - sk.cancel(); - releaseSelector(sel); - } - } - result.setResult(n); - } catch (Exception x) { - if (x instanceof ClosedChannelException) x = new AsynchronousCloseException(); - result.setFailure(x); - } - Invoker.invokeUnchecked(result); - } - }; - try { - group.executeOnPooledThread(task); - } catch (RejectedExecutionException ree) { - throw new ShutdownChannelGroupException(); - } - return result; - } - - @Override - public Future read(ByteBuffer dst) { - return implRead(dst, 0L, TimeUnit.MILLISECONDS, null, null); - } - - public void read(ByteBuffer dst, long timeout, TimeUnit unit, A attachment, CompletionHandler handler) { - if (handler == null) throw new NullPointerException("'handler' is null"); - implRead(dst, timeout, unit, attachment, handler); - } - - @Override - public AsyncDatagramChannel bind(SocketAddress local) throws IOException { - dc.bind(local); - return this; - } - - @Override - public SocketAddress getLocalAddress() throws IOException { - return dc.getLocalAddress(); - } - - @Override - public AsyncDatagramChannel setOption(SocketOption name, T value) throws IOException { - dc.setOption(name, value); - return this; - } - - @Override - public T getOption(SocketOption name) throws IOException { - return dc.getOption(name); - } - - @Override - public Set> supportedOptions() { - return dc.supportedOptions(); - } - - public SocketAddress getRemoteAddress() throws IOException { - return dc.getRemoteAddress(); - } - - private static class SelectorWrapper { - - private Selector sel; - - private SelectorWrapper(Selector sel) { - this.sel = sel; - Cleaner.create(this, new Closer(sel)); - } - - private static class Closer implements Runnable { - - private Selector sel; - - private Closer(Selector sel) { - this.sel = sel; - } - - public void run() { - try { - sel.close(); - } catch (Exception th) { - //throw new Error(th); - } - } - } - - public Selector get() { - return sel; - } - } - - private static ThreadLocal> localSelector - = new ThreadLocal>(); - - // Hold a reference to the selWrapper object to prevent it from - // being cleaned when the temporary selector wrapped is on lease. - private static ThreadLocal localSelectorWrapper - = new ThreadLocal(); - - static Selector getTemporarySelector(SelectableChannel sc) - throws IOException { - SoftReference ref = localSelector.get(); - SelectorWrapper selWrapper = null; - Selector sel = null; - if (ref == null - || ((selWrapper = ref.get()) == null) - || ((sel = selWrapper.get()) == null) - || (sel.provider() != sc.provider())) { - sel = sc.provider().openSelector(); - selWrapper = new SelectorWrapper(sel); - localSelector.set(new SoftReference(selWrapper)); - } - localSelectorWrapper.set(selWrapper); - return sel; - } - - static void releaseTemporarySelector(Selector sel) - throws IOException { - // Selector should be empty - sel.selectNow(); // Flush cancelled keys - assert sel.keys().isEmpty() : "Temporary selector not empty"; - localSelectorWrapper.set(null); - } - -} - -final class AsynchronousChannelGroupProxy extends AsynchronousChannelGroup { - - private final AsynchronousChannelGroup group; - - private final MethodHandle executeOnPooledThread; - - private final MethodHandle attachForeignChannel; - - private final MethodHandle detachForeignChannel; - - public AsynchronousChannelGroupProxy(AsynchronousChannelGroup group) { - super(group.provider()); - this.group = group; - MethodHandle method1 = null, method2 = null, method3 = null; - try { - Method m = findGroupMethod(group.getClass(), "executeOnPooledThread", Runnable.class); - m.setAccessible(true); - method1 = MethodHandles.lookup().unreflect(m); - - m = findGroupMethod(group.getClass(), "attachForeignChannel", Channel.class, FileDescriptor.class); - m.setAccessible(true); - method2 = MethodHandles.lookup().unreflect(m); - - m = findGroupMethod(group.getClass(), "detachForeignChannel", Object.class); - m.setAccessible(true); - method3 = MethodHandles.lookup().unreflect(m); - } catch (Exception e) { - e.printStackTrace(); - } - this.executeOnPooledThread = method1; - this.attachForeignChannel = method2; - this.detachForeignChannel = method3; - } - - private static Method findGroupMethod(Class clazz, String methodname, Class... params) throws Exception { - if (clazz == Object.class) return null; - try { - return clazz.getDeclaredMethod(methodname, params); - } catch (NoSuchMethodException e) { - return findGroupMethod(clazz.getSuperclass(), methodname, params); - } - } - - @Override - public boolean isShutdown() { - return group.isShutdown(); - } - - @Override - public boolean isTerminated() { - return group.isTerminated(); - } - - @Override - public void shutdown() { - group.shutdown(); - } - - @Override - public void shutdownNow() throws IOException { - group.shutdownNow(); - } - - @Override - public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { - return group.awaitTermination(timeout, unit); - } - - Object attachForeignChannel(Channel channel, FileDescriptor fdo) throws IOException { - try { - return attachForeignChannel.invoke(group, channel, fdo); - } catch (Throwable e) { - throw new IOException(e); - } - } - - void detachForeignChannel(Object key) { - try { - detachForeignChannel.invoke(group, key); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - final void executeOnPooledThread(Runnable task) { - try { - executeOnPooledThread.invoke(group, task); - } catch (Throwable e) { - e.printStackTrace(); - } - } - -} - -final class PendingFuture implements Future { - - private static final CancellationException CANCELLED = new CancellationException(); - - private final AsynchronousChannel channel; - - private final CompletionHandler handler; - - private final A attachment; - - // true if result (or exception) is available - private volatile boolean haveResult; - - private volatile V result; - - private volatile Throwable exc; - - // latch for waiting (created lazily if needed) - private CountDownLatch latch; - - // optional timer task that is cancelled when result becomes available - private Future timeoutTask; - - // optional context object - private volatile Object context; - - PendingFuture(AsynchronousChannel channel, CompletionHandler handler, A attachment, Object context) { - this.channel = channel; - this.handler = handler; - this.attachment = attachment; - this.context = context; - } - - PendingFuture(AsynchronousChannel channel, CompletionHandler handler, A attachment) { - this.channel = channel; - this.handler = handler; - this.attachment = attachment; - } - - PendingFuture(AsynchronousChannel channel) { - this(channel, null, null); - } - - PendingFuture(AsynchronousChannel channel, Object context) { - this(channel, null, null, context); - } - - AsynchronousChannel channel() { - return channel; - } - - CompletionHandler handler() { - return handler; - } - - A attachment() { - return attachment; - } - - void setContext(Object context) { - this.context = context; - } - - Object getContext() { - return context; - } - - void setTimeoutTask(Future task) { - synchronized (this) { - if (haveResult) { - task.cancel(false); - } else { - this.timeoutTask = task; - } - } - } - - // creates latch if required; return true if caller needs to wait - private boolean prepareForWait() { - synchronized (this) { - if (haveResult) { - return false; - } else { - if (latch == null) - latch = new CountDownLatch(1); - return true; - } - } - } - - /** - * Sets the result, or a no-op if the result or exception is already set. - */ - void setResult(V res) { - synchronized (this) { - if (haveResult) - return; - result = res; - haveResult = true; - if (timeoutTask != null) - timeoutTask.cancel(false); - if (latch != null) - latch.countDown(); - } - } - - /** - * Sets the result, or a no-op if the result or exception is already set. - */ - void setFailure(Throwable x) { - if (!(x instanceof IOException) && !(x instanceof SecurityException)) - x = new IOException(x); - synchronized (this) { - if (haveResult) - return; - exc = x; - haveResult = true; - if (timeoutTask != null) - timeoutTask.cancel(false); - if (latch != null) - latch.countDown(); - } - } - - /** - * Sets the result - */ - void setResult(V res, Throwable x) { - if (x == null) { - setResult(res); - } else { - setFailure(x); - } - } - - @Override - public V get() throws ExecutionException, InterruptedException { - if (!haveResult) { - boolean needToWait = prepareForWait(); - if (needToWait) - latch.await(); - } - if (exc != null) { - if (exc == CANCELLED) - throw new CancellationException(); - throw new ExecutionException(exc); - } - return result; - } - - @Override - public V get(long timeout, TimeUnit unit) - throws ExecutionException, InterruptedException, TimeoutException { - if (!haveResult) { - boolean needToWait = prepareForWait(); - if (needToWait) - if (!latch.await(timeout, unit)) throw new TimeoutException(); - } - if (exc != null) { - if (exc == CANCELLED) - throw new CancellationException(); - throw new ExecutionException(exc); - } - return result; - } - - Throwable exception() { - return (exc != CANCELLED) ? exc : null; - } - - V value() { - return result; - } - - @Override - public boolean isCancelled() { - return (exc == CANCELLED); - } - - @Override - public boolean isDone() { - return haveResult; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - synchronized (this) { - if (haveResult) - return false; // already completed - - // notify channel - if (channel() instanceof AsyncDatagramChannel) - ((AsyncDatagramChannel) channel()).onCancel(this); - - // set result and cancel timer - exc = CANCELLED; - haveResult = true; - if (timeoutTask != null) - timeoutTask.cancel(false); - } - - // close channel if forceful cancel - if (mayInterruptIfRunning) { - try { - channel().close(); - } catch (IOException ignore) { - } - } - - // release waiters - if (latch != null) - latch.countDown(); - return true; - } -} - -final class CompletedFuture implements Future { - - private final V result; - - private final Throwable exc; - - private CompletedFuture(V result, Throwable exc) { - this.result = result; - this.exc = exc; - } - - static CompletedFuture withResult(V result) { - return new CompletedFuture(result, null); - } - - static CompletedFuture withFailure(Throwable exc) { - // exception must be IOException or SecurityException - if (!(exc instanceof IOException) && !(exc instanceof SecurityException)) - exc = new IOException(exc); - return new CompletedFuture(null, exc); - } - - static CompletedFuture withResult(V result, Throwable exc) { - if (exc == null) { - return withResult(result); - } else { - return withFailure(exc); - } - } - - @Override - public V get() throws ExecutionException { - if (exc != null) - throw new ExecutionException(exc); - return result; - } - - @Override - public V get(long timeout, TimeUnit unit) throws ExecutionException { - if (unit == null) - throw new NullPointerException(); - if (exc != null) - throw new ExecutionException(exc); - return result; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return true; - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } -} - -class Invoker { - - private Invoker() { - } - - // maximum number of completion handlers that may be invoked on the current - // thread before it re-directs invocations to the thread pool. This helps - // avoid stack overflow and lessens the risk of starvation. - private static final int maxHandlerInvokeCount = AccessController.doPrivileged( - new GetIntegerAction("sun.nio.ch.maxCompletionHandlersOnStack", 16)); - - // Per-thread object with reference to channel group and a counter for - // the number of completion handlers invoked. This should be reset to 0 - // when all completion handlers have completed. - static class GroupAndInvokeCount { - - private final AsynchronousChannelGroup group; - - private int handlerInvokeCount; - - GroupAndInvokeCount(AsynchronousChannelGroup group) { - this.group = group; - } - - AsynchronousChannelGroup group() { - return group; - } - - int invokeCount() { - return handlerInvokeCount; - } - - void setInvokeCount(int value) { - handlerInvokeCount = value; - } - - void resetInvokeCount() { - handlerInvokeCount = 0; - } - - void incrementInvokeCount() { - handlerInvokeCount++; - } - } - - private static final ThreadLocal myGroupAndInvokeCount - = new ThreadLocal() { - @Override - protected GroupAndInvokeCount initialValue() { - return null; - } - }; - - /** - * Binds this thread to the given group - */ - static void bindToGroup(AsynchronousChannelGroup group) { - myGroupAndInvokeCount.set(new GroupAndInvokeCount(group)); - } - - /** - * Returns the GroupAndInvokeCount object for this thread. - */ - static GroupAndInvokeCount getGroupAndInvokeCount() { - return myGroupAndInvokeCount.get(); - } - - /** - * Returns true if the current thread is in a channel group's thread pool - */ - static boolean isBoundToAnyGroup() { - return myGroupAndInvokeCount.get() != null; - } - - /* - * Returns true if the current thread is in the given channel's thread pool - * and we haven't exceeded the maximum number of handler frames on the stack. - */ - static boolean mayInvokeDirect(GroupAndInvokeCount myGroupAndInvokeCount, - AsynchronousChannelGroup group) { - if ((myGroupAndInvokeCount != null) - && (myGroupAndInvokeCount.group() == group) - && (myGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount)) { - return true; - } - return false; - } - - /** - * Invoke handler without checking the thread identity or number of handlers on the thread stack. - */ - static void invokeUnchecked(CompletionHandler handler, - A attachment, - V value, - Throwable exc) { - if (exc == null) { - handler.completed(value, attachment); - } else { - handler.failed(exc, attachment); - } - - // clear interrupt - Thread.interrupted(); - } - - /** - * Invoke handler assuming thread identity already checked - */ - static void invokeDirect(GroupAndInvokeCount myGroupAndInvokeCount, - CompletionHandler handler, - A attachment, - V result, - Throwable exc) { - myGroupAndInvokeCount.incrementInvokeCount(); - Invoker.invokeUnchecked(handler, attachment, result, exc); - } - - /** - * Invokes the handler. If the current thread is in the channel group's thread pool then the handler is invoked directly, otherwise it is invoked indirectly. - */ - static void invoke(AsynchronousChannel channel, - CompletionHandler handler, - A attachment, - V result, - Throwable exc) { - boolean invokeDirect = false; - boolean identityOkay = false; - GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get(); - if (thisGroupAndInvokeCount != null) { - if ((thisGroupAndInvokeCount.group() == ((AsyncDatagramChannel) channel).group())) - identityOkay = true; - if (identityOkay - && (thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount)) { - // group match - invokeDirect = true; - } - } - if (invokeDirect) { - invokeDirect(thisGroupAndInvokeCount, handler, attachment, result, exc); - } else { - try { - invokeIndirectly(channel, handler, attachment, result, exc); - } catch (RejectedExecutionException ree) { - // channel group shutdown; fallback to invoking directly - // if the current thread has the right identity. - if (identityOkay) { - invokeDirect(thisGroupAndInvokeCount, - handler, attachment, result, exc); - } else { - throw new ShutdownChannelGroupException(); - } - } - } - } - - /** - * Invokes the handler indirectly via the channel group's thread pool. - */ - static void invokeIndirectly(AsynchronousChannel channel, - final CompletionHandler handler, - final A attachment, - final V result, - final Throwable exc) { - try { - ((AsyncDatagramChannel) channel).group().executeOnPooledThread(new Runnable() { - public void run() { - GroupAndInvokeCount thisGroupAndInvokeCount - = myGroupAndInvokeCount.get(); - if (thisGroupAndInvokeCount != null) - thisGroupAndInvokeCount.setInvokeCount(1); - invokeUnchecked(handler, attachment, result, exc); - } - }); - } catch (RejectedExecutionException ree) { - throw new ShutdownChannelGroupException(); - } - } - - /** - * Invokes the handler "indirectly" in the given Executor - */ - static void invokeIndirectly(final CompletionHandler handler, - final A attachment, - final V value, - final Throwable exc, - Executor executor) { - try { - executor.execute(new Runnable() { - public void run() { - invokeUnchecked(handler, attachment, value, exc); - } - }); - } catch (RejectedExecutionException ree) { - throw new ShutdownChannelGroupException(); - } - } - - /** - * Invokes the given task on the thread pool associated with the given channel. If the current thread is in the thread pool then the task is invoked directly. - */ - static void invokeOnThreadInThreadPool(AsyncDatagramChannel channel, - Runnable task) { - boolean invokeDirect; - GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get(); - AsynchronousChannelGroupProxy targetGroup = channel.group(); - if (thisGroupAndInvokeCount == null) { - invokeDirect = false; - } else { - invokeDirect = (thisGroupAndInvokeCount.group == targetGroup); - } - try { - if (invokeDirect) { - task.run(); - } else { - targetGroup.executeOnPooledThread(task); - } - } catch (RejectedExecutionException ree) { - throw new ShutdownChannelGroupException(); - } - } - - /** - * Invoke handler with completed result. This method does not check the thread identity or the number of handlers on the thread stack. - */ - static void invokeUnchecked(PendingFuture future) { - assert future.isDone(); - CompletionHandler handler = future.handler(); - if (handler != null) { - invokeUnchecked(handler, - future.attachment(), - future.value(), - future.exception()); - } - } - - /** - * Invoke handler with completed result. If the current thread is in the channel group's thread pool then the handler is invoked directly, otherwise it is invoked indirectly. - */ - static void invoke(PendingFuture future) { - assert future.isDone(); - CompletionHandler handler = future.handler(); - if (handler != null) { - invoke(future.channel(), - handler, - future.attachment(), - future.value(), - future.exception()); - } - } - - /** - * Invoke handler with completed result. The handler is invoked indirectly, via the channel group's thread pool. - */ - static void invokeIndirectly(PendingFuture future) { - assert future.isDone(); - CompletionHandler handler = future.handler(); - if (handler != null) { - invokeIndirectly(future.channel(), - handler, - future.attachment(), - future.value(), - future.exception()); - } - } -} diff --git a/src/com/wentch/redkale/net/Context.java b/src/com/wentch/redkale/net/Context.java deleted file mode 100644 index a57dd8577..000000000 --- a/src/com/wentch/redkale/net/Context.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import com.wentch.redkale.convert.bson.*; -import com.wentch.redkale.convert.json.*; -import com.wentch.redkale.util.*; -import com.wentch.redkale.watch.*; -import java.net.*; -import java.nio.*; -import java.nio.charset.*; -import java.util.concurrent.*; -import java.util.function.*; -import java.util.logging.*; - -/** - * - * @author zhangjx - */ -public class Context { - - private static final Charset UTF8 = Charset.forName("UTF-8"); - - protected final long serverStartTime; - - protected final ExecutorService executor; - - protected final int bufferCapacity; - - protected final ObjectPool bufferPool; - - protected final ObjectPool responsePool; - - protected final PrepareServlet prepare; - - private final InetSocketAddress address; - - protected final Charset charset; - - protected final int maxbody; - - protected final int readTimeoutSecond; - - protected final int writeTimeoutSecond; - - protected final Logger logger; - - protected final BsonFactory bsonFactory; - - protected final JsonFactory jsonFactory; - - protected final WatchFactory watch; - - public Context(long serverStartTime, Logger logger, ExecutorService executor, int bufferCapacity, ObjectPool bufferPool, ObjectPool responsePool, - final int maxbody, Charset charset, InetSocketAddress address, final PrepareServlet prepare, final WatchFactory watch, - final int readTimeoutSecond, final int writeTimeoutSecond) { - this.serverStartTime = serverStartTime; - this.logger = logger; - this.executor = executor; - this.bufferCapacity = bufferCapacity; - this.bufferPool = bufferPool; - this.responsePool = responsePool; - this.maxbody = maxbody; - this.charset = UTF8.equals(charset) ? null : charset; - this.address = address; - this.prepare = prepare; - this.watch = watch; - this.readTimeoutSecond = readTimeoutSecond; - this.writeTimeoutSecond = writeTimeoutSecond; - this.jsonFactory = JsonFactory.root(); - this.bsonFactory = BsonFactory.root(); - } - - public int getMaxbody() { - return maxbody; - } - - public InetSocketAddress getServerAddress() { - return address; - } - - public long getServerStartTime() { - return serverStartTime; - } - - public Charset getCharset() { - return charset; - } - - public void submit(Runnable r) { - executor.submit(r); - } - - public int getBufferCapacity() { - return bufferCapacity; - } - - public Supplier getBufferSupplier() { - return bufferPool; - } - - public ByteBuffer pollBuffer() { - return bufferPool.get(); - } - - public void offerBuffer(ByteBuffer buffer) { - bufferPool.offer(buffer); - } - - public Logger getLogger() { - return logger; - } - - public int getReadTimeoutSecond() { - return readTimeoutSecond; - } - - public int getWriteTimeoutSecond() { - return writeTimeoutSecond; - } - - public JsonConvert getJsonConvert() { - return jsonFactory.getConvert(); - } - - public BsonConvert getBsonConvert() { - return bsonFactory.getConvert(); - } -} diff --git a/src/com/wentch/redkale/net/PrepareRunner.java b/src/com/wentch/redkale/net/PrepareRunner.java deleted file mode 100644 index 07f5e26a3..000000000 --- a/src/com/wentch/redkale/net/PrepareRunner.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import com.wentch.redkale.util.*; -import java.nio.*; -import java.nio.channels.*; -import java.util.logging.*; - -/** - * - * @author zhangjx - */ -@SuppressWarnings("unchecked") -public final class PrepareRunner implements Runnable { - - private final AsyncConnection channel; - - private final Context context; - - private ByteBuffer data; - - public PrepareRunner(Context context, AsyncConnection channel, ByteBuffer data) { - this.context = context; - this.channel = channel; - this.data = data; - } - - @Override - public void run() { - final PrepareServlet prepare = context.prepare; - final ObjectPool responsePool = context.responsePool; - if (data != null) { - final Response response = responsePool.get(); - response.init(channel); - try { - prepare.prepare(data, response.request, response); - } catch (Throwable t) { - context.logger.log(Level.WARNING, "prepare servlet abort, forece to close channel ", t); - response.finish(true); - } - return; - } - final ByteBuffer buffer = context.pollBuffer(); - try { - channel.read(buffer, null, new CompletionHandler() { - @Override - public void completed(Integer count, Void attachment1) { - if (count < 1 && buffer.remaining() == buffer.limit()) { - try { - context.offerBuffer(buffer); - channel.close(); - } catch (Exception e) { - context.logger.log(Level.FINEST, "PrepareRunner close channel erroneous on no read bytes", e); - } - return; - } -// { //测试 -// buffer.flip(); -// byte[] bs = new byte[buffer.remaining()]; -// buffer.get(bs); -// System.println(new String(bs)); -// } - buffer.flip(); - final Response response = responsePool.get(); - response.init(channel); - try { - prepare.prepare(buffer, response.request, response); - } catch (Throwable t) { //此处不可 context.offerBuffer(buffer); 以免prepare.prepare内部异常导致重复 offerBuffer - context.logger.log(Level.WARNING, "prepare servlet abort, forece to close channel ", t); - response.finish(true); - } - } - - @Override - public void failed(Throwable exc, Void attachment2) { - context.offerBuffer(buffer); - try { - channel.close(); - } catch (Exception e) { - } - if (exc != null) context.logger.log(Level.FINEST, "Servlet Handler read channel erroneous, forece to close channel ", exc); - } - }); - } catch (Exception te) { - context.offerBuffer(buffer); - try { - channel.close(); - } catch (Exception e) { - } - if (te != null) context.logger.log(Level.FINEST, "Servlet read channel erroneous, forece to close channel ", te); - } - } - -} diff --git a/src/com/wentch/redkale/net/PrepareServlet.java b/src/com/wentch/redkale/net/PrepareServlet.java deleted file mode 100644 index d2399e425..000000000 --- a/src/com/wentch/redkale/net/PrepareServlet.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import java.io.*; -import java.nio.*; -import java.nio.channels.*; -import java.util.concurrent.atomic.*; -import java.util.logging.*; - -/** - * - * @author zhangjx - * @param - * @param

- */ -public abstract class PrepareServlet> implements Servlet { - - protected final AtomicLong executeCounter = new AtomicLong(); //执行请求次数 - - protected final AtomicLong illRequestCounter = new AtomicLong(); //错误请求次数 - - public final void prepare(final ByteBuffer buffer, final R request, final P response) throws IOException { - executeCounter.incrementAndGet(); - final int rs = request.readHeader(buffer); - if (rs < 0) { - response.context.offerBuffer(buffer); - if (rs != Integer.MIN_VALUE) illRequestCounter.incrementAndGet(); - response.finish(true); - } else if (rs == 0) { - response.context.offerBuffer(buffer); - request.prepare(); - this.execute(request, response); - } else { - buffer.clear(); - final AtomicInteger ai = new AtomicInteger(rs); - request.channel.read(buffer, buffer, new CompletionHandler() { - - @Override - public void completed(Integer result, ByteBuffer attachment) { - buffer.flip(); - ai.addAndGet(-request.readBody(buffer)); - if (ai.get() > 0) { - buffer.clear(); - request.channel.read(buffer, buffer, this); - } else { - response.context.offerBuffer(buffer); - request.prepare(); - try { - execute(request, response); - } catch (Exception e) { - illRequestCounter.incrementAndGet(); - response.finish(true); - request.context.logger.log(Level.WARNING, "prepare servlet abort, forece to close channel ", e); - } - } - } - - @Override - public void failed(Throwable exc, ByteBuffer attachment) { - illRequestCounter.incrementAndGet(); - response.context.offerBuffer(buffer); - response.finish(true); - if (exc != null) request.context.logger.log(Level.FINER, "Servlet read channel erroneous, forece to close channel ", exc); - } - }); - } - } - -} diff --git a/src/com/wentch/redkale/net/ProtocolServer.java b/src/com/wentch/redkale/net/ProtocolServer.java deleted file mode 100644 index d39be0f61..000000000 --- a/src/com/wentch/redkale/net/ProtocolServer.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import java.io.IOException; -import java.net.*; -import java.nio.ByteBuffer; -import java.nio.channels.*; -import java.util.*; -import java.util.concurrent.*; - -/** - * - * @author zhangjx - */ -public abstract class ProtocolServer { - - protected static final boolean winos = System.getProperty("os.name").contains("Window"); - - public abstract void open() throws IOException; - - public abstract void bind(SocketAddress local, int backlog) throws IOException; - - public abstract Set> supportedOptions(); - - public abstract void setOption(SocketOption name, T value) throws IOException; - - public abstract void accept(); - - public abstract void close() throws IOException; - - public abstract AsynchronousChannelGroup getChannelGroup(); - - //--------------------------------------------------------------------- - public static ProtocolServer create(String protocol, Context context) { - if ("TCP".equalsIgnoreCase(protocol)) return new ProtocolTCPServer(context); - if ("UDP".equalsIgnoreCase(protocol)) return new ProtocolUDPServer(context); - throw new RuntimeException("ProtocolServer not support protocol " + protocol); - } - - private static final class ProtocolUDPServer extends ProtocolServer { - - private boolean running; - - private final Context context; - - private DatagramChannel serverChannel; - - public ProtocolUDPServer(Context context) { - this.context = context; - } - - @Override - public void open() throws IOException { - DatagramChannel ch = DatagramChannel.open(); - ch.configureBlocking(true); - this.serverChannel = ch; - } - - @Override - public void bind(SocketAddress local, int backlog) throws IOException { - this.serverChannel.bind(local); - } - - @Override - public void setOption(SocketOption name, T value) throws IOException { - this.serverChannel.setOption(name, value); - } - - @Override - public Set> supportedOptions() { - return this.serverChannel.supportedOptions(); - } - - @Override - public void accept() { - final DatagramChannel serchannel = this.serverChannel; - final int readTimeoutSecond = this.context.readTimeoutSecond; - final int writeTimeoutSecond = this.context.writeTimeoutSecond; - final CountDownLatch cdl = new CountDownLatch(1); - this.running = true; - new Thread() { - @Override - public void run() { - cdl.countDown(); - while (running) { - final ByteBuffer buffer = context.pollBuffer(); - try { - SocketAddress address = serchannel.receive(buffer); - buffer.flip(); - AsyncConnection conn = AsyncConnection.create(serchannel, address, false, readTimeoutSecond, writeTimeoutSecond); - context.submit(new PrepareRunner(context, conn, buffer)); - } catch (Exception e) { - context.offerBuffer(buffer); - } - } - } - }.start(); - try { - cdl.await(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Override - public void close() throws IOException { - this.running = false; - this.serverChannel.close(); - } - - @Override - public AsynchronousChannelGroup getChannelGroup() { - return null; - } - - } - - private static final class ProtocolTCPServer extends ProtocolServer { - - private final Context context; - - private AsynchronousChannelGroup group; - - private AsynchronousServerSocketChannel serverChannel; - - public ProtocolTCPServer(Context context) { - this.context = context; - } - - @Override - public void open() throws IOException { - group = AsynchronousChannelGroup.withCachedThreadPool(context.executor, 1); - this.serverChannel = AsynchronousServerSocketChannel.open(group); - } - - @Override - public void bind(SocketAddress local, int backlog) throws IOException { - this.serverChannel.bind(local, backlog); - } - - @Override - public void setOption(SocketOption name, T value) throws IOException { - this.serverChannel.setOption(name, value); - } - - @Override - public Set> supportedOptions() { - return this.serverChannel.supportedOptions(); - } - - @Override - public void accept() { - final AsynchronousServerSocketChannel serchannel = this.serverChannel; - serchannel.accept(null, new CompletionHandler() { - - @Override - public void completed(final AsynchronousSocketChannel channel, Void attachment) { - serchannel.accept(null, this); - context.submit(new PrepareRunner(context, AsyncConnection.create(channel, null, context.readTimeoutSecond, context.writeTimeoutSecond), null)); - } - - @Override - public void failed(Throwable exc, Void attachment) { - serchannel.accept(null, this); - //if (exc != null) context.logger.log(Level.FINEST, AsynchronousServerSocketChannel.class.getSimpleName() + " accept erroneous", exc); - } - }); - } - - @Override - public void close() throws IOException { - this.serverChannel.close(); - } - - @Override - public AsynchronousChannelGroup getChannelGroup() { - return this.group; - } - } - -} diff --git a/src/com/wentch/redkale/net/Request.java b/src/com/wentch/redkale/net/Request.java deleted file mode 100644 index fa9c2d1b1..000000000 --- a/src/com/wentch/redkale/net/Request.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import com.wentch.redkale.convert.bson.*; -import com.wentch.redkale.convert.json.*; -import java.nio.*; -import java.util.*; - -/** - * - * @author zhangjx - */ -public abstract class Request { - - protected final Context context; - - protected final BsonConvert bsonConvert; - - protected final JsonConvert jsonConvert; - - protected long createtime; - - protected boolean keepAlive; - - protected AsyncConnection channel; - - /** - * properties 与 attributes 的区别在于:调用recycle时, attributes会被清空而properties会保留; - * properties 通常存放需要永久绑定在request里的一些对象 - */ - private final Map properties = new HashMap<>(); - - protected final Map attributes = new HashMap<>(); - - protected Request(Context context) { - this.context = context; - this.bsonConvert = context.getBsonConvert(); - this.jsonConvert = context.getJsonConvert(); - } - - /** - * 返回值:Integer.MIN_VALUE: 帧数据; -1:数据不合法; 0:解析完毕; >0: 需再读取的字节数。 - * - * @param buffer - * @return - */ - protected abstract int readHeader(ByteBuffer buffer); - - /** - * 读取buffer,并返回读取的有效数据长度 - * - * @param buffer - * @return - */ - protected abstract int readBody(ByteBuffer buffer); - - protected abstract void prepare(); - - protected void recycle() { - createtime = 0; - keepAlive = false; - attributes.clear(); - channel = null; // close it by response - } - - protected void setProperty(String name, Object value) { - properties.put(name, value); - } - - @SuppressWarnings("unchecked") - protected T getProperty(String name) { - return (T) properties.get(name); - } - - protected void removeProperty(String name) { - properties.remove(name); - } - - protected Map getProperties() { - return properties; - } - - public void setAttribute(String name, Object value) { - attributes.put(name, value); - } - - @SuppressWarnings("unchecked") - public T getAttribute(String name) { - return (T) attributes.get(name); - } - - public void removeAttribute(String name) { - attributes.remove(name); - } - - public Map getAttributes() { - return attributes; - } - - public Context getContext() { - return this.context; - } - - public long getCreatetime() { - return createtime; - } - -} diff --git a/src/com/wentch/redkale/net/Response.java b/src/com/wentch/redkale/net/Response.java deleted file mode 100644 index a3c6d30d2..000000000 --- a/src/com/wentch/redkale/net/Response.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import java.nio.*; -import java.nio.channels.*; - -/** - * - * @author zhangjx - * @param - */ -@SuppressWarnings("unchecked") -public abstract class Response { - - protected final Context context; - - protected final R request; - - protected AsyncConnection channel; - - private boolean inited = true; - - protected Runnable recycleListener; - - private final CompletionHandler finishHandler = new CompletionHandler() { - - @Override - public void completed(Integer result, ByteBuffer attachment) { - if (attachment.hasRemaining()) { - channel.write(attachment, attachment, this); - } else { - context.offerBuffer(attachment); - finish(); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer attachment) { - context.offerBuffer(attachment); - finish(true); - } - - }; - - private final CompletionHandler finishHandler2 = new CompletionHandler() { - - @Override - public void completed(Integer result, ByteBuffer[] attachments) { - int index = -1; - for (int i = 0; i < attachments.length; i++) { - if (attachments[i].hasRemaining()) { - index = i; - break; - } else { - context.offerBuffer(attachments[i]); - } - } - if (index == 0) { - channel.write(attachments, attachments, this); - } else if (index > 0) { - ByteBuffer[] newattachs = new ByteBuffer[attachments.length - index]; - System.arraycopy(attachments, index, newattachs, 0, newattachs.length); - channel.write(newattachs, newattachs, this); - } else { - finish(); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer[] attachments) { - for (ByteBuffer attachment : attachments) { - context.offerBuffer(attachment); - } - finish(true); - } - - }; - - protected Response(Context context, final R request) { - this.context = context; - this.request = request; - } - - protected AsyncConnection removeChannel() { - AsyncConnection ch = this.channel; - this.channel = null; - return ch; - } - - protected void prepare() { - inited = true; - } - - protected boolean recycle() { - if (!inited) return false; - boolean keepAlive = request.keepAlive; - if (recycleListener != null) { - try { - recycleListener.run(); - } catch (Exception e) { - System.err.println(request); - e.printStackTrace(); - } - recycleListener = null; - } - request.recycle(); - if (channel != null) { - if (keepAlive) { - this.context.submit(new PrepareRunner(context, channel, null)); - } else { - try { - if (channel.isOpen()) channel.close(); - } catch (Exception e) { - } - } - channel = null; - } - this.inited = false; - return true; - } - - protected void refuseAlive() { - this.request.keepAlive = false; - } - - protected void init(AsyncConnection channel) { - this.channel = channel; - this.request.channel = channel; - this.request.createtime = System.currentTimeMillis(); - } - - public void setRecycleListener(Runnable recycleListener) { - this.recycleListener = recycleListener; - } - - public void finish() { - this.finish(false); - } - - public void finish(boolean kill) { - //System.println("耗时: " + (System.currentTimeMillis() - request.createtime)); - if (kill) refuseAlive(); - this.context.responsePool.offer(this); - } - - public void finish(ByteBuffer buffer) { - this.channel.write(buffer, buffer, finishHandler); - } - - public void finish(boolean kill, ByteBuffer buffer) { - if (kill) refuseAlive(); - this.channel.write(buffer, buffer, finishHandler); - } - - public void finish(ByteBuffer... buffers) { - this.channel.write(buffers, buffers, finishHandler2); - } - - public void finish(boolean kill, ByteBuffer... buffers) { - if (kill) refuseAlive(); - this.channel.write(buffers, buffers, finishHandler2); - } - - protected void send(final ByteBuffer buffer, final A attachment, final CompletionHandler handler) { - this.channel.write(buffer, attachment, new CompletionHandler() { - - @Override - public void completed(Integer result, A attachment) { - if (buffer.hasRemaining()) { - channel.write(buffer, attachment, this); - } else { - context.offerBuffer(buffer); - if (handler != null) handler.completed(result, attachment); - } - } - - @Override - public void failed(Throwable exc, A attachment) { - context.offerBuffer(buffer); - if (handler != null) handler.failed(exc, attachment); - } - - }); - } - - protected void send(final ByteBuffer[] buffers, A attachment, CompletionHandler handler) { - this.channel.write(buffers, attachment, new CompletionHandler() { - - @Override - public void completed(Integer result, A attachment) { - int index = -1; - for (int i = 0; i < buffers.length; i++) { - if (buffers[i].hasRemaining()) { - index = i; - break; - } - context.offerBuffer(buffers[i]); - } - if (index == 0) { - channel.write(buffers, attachment, this); - } else if (index > 0) { - ByteBuffer[] newattachs = new ByteBuffer[buffers.length - index]; - System.arraycopy(buffers, index, newattachs, 0, newattachs.length); - channel.write(newattachs, attachment, this); - } else { - if (handler != null) handler.completed(result, attachment); - } - } - - @Override - public void failed(Throwable exc, A attachment) { - for (ByteBuffer buffer : buffers) { - context.offerBuffer(buffer); - } - if (handler != null) handler.failed(exc, attachment); - } - - }); - } - - public Context getContext() { - return context; - } -} diff --git a/src/com/wentch/redkale/net/SSLBuilder.java b/src/com/wentch/redkale/net/SSLBuilder.java deleted file mode 100644 index a1cf9ee69..000000000 --- a/src/com/wentch/redkale/net/SSLBuilder.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import java.nio.*; -import java.security.*; -import javax.net.ssl.*; - -/** - * - * @author zhangjx - */ -public class SSLBuilder { - - private static SSLContext sslContext; - - static { - try { - char[] keypasswd = new char[32]; - final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - keyStore.load(null, keypasswd); - final String algorithm = System.getProperty("ssl.algorithm", KeyManagerFactory.getDefaultAlgorithm()); - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); - kmf.init(keyStore, keypasswd); - SSLContext sslContext0 = SSLContext.getInstance("TLS"); - sslContext0.init(kmf.getKeyManagers(), null, new SecureRandom()); - sslContext = sslContext0; - } catch (Exception e) { - throw new Error(e); - } - } - - private final SSLEngine sslEngine; - - private int appBufferSize; - - private int netBufferSize; - - public SSLBuilder() { - sslEngine = sslContext.createSSLEngine(); - //sslEngine.setEnabledCipherSuites(null); - //sslEngine.setEnabledProtocols(null); - - sslEngine.setUseClientMode(false); - sslEngine.setWantClientAuth(false); - sslEngine.setNeedClientAuth(false); - //--------------------------- - updateBufferSizes(); - } - - private void updateBufferSizes() { - final SSLSession session = sslEngine.getSession(); - appBufferSize = session.getApplicationBufferSize(); - netBufferSize = session.getPacketBufferSize(); - } - - public static void main(String[] args) throws Exception { - - } - - private static int getSSLPacketSize(final ByteBuffer buf) throws SSLException { - - /* - * SSLv2 length field is in bytes 0/1 - * SSLv3/TLS length field is in bytes 3/4 - */ - if (buf.remaining() < 5) return -1; - - final byte byte0; - final byte byte1; - final byte byte2; - final byte byte3; - final byte byte4; - - if (buf.hasArray()) { - final byte[] array = buf.array(); - int pos = buf.arrayOffset() + buf.position(); - byte0 = array[pos++]; - byte1 = array[pos++]; - byte2 = array[pos++]; - byte3 = array[pos++]; - byte4 = array[pos]; - } else { - int pos = buf.position(); - byte0 = buf.get(pos++); - byte1 = buf.get(pos++); - byte2 = buf.get(pos++); - byte3 = buf.get(pos++); - byte4 = buf.get(pos); - } - - int len; - - /* - * If we have already verified previous packets, we can - * ignore the verifications steps, and jump right to the - * determination. Otherwise, try one last hueristic to - * see if it's SSL/TLS. - */ - if (byte0 >= 20 && byte0 <= 23) { - /* - * Last sanity check that it's not a wild record - */ - final byte major = byte1; - final byte minor = byte2; - final int v = (major << 8) | minor & 0xff; - - // Check if too old (currently not possible) - // or if the major version does not match. - // The actual version negotiation is in the handshaker classes - if ((v < 0x0300) || (major > 0x03)) { - throw new SSLException("Unsupported record version major=" + major + " minor=" + minor); - } - - /* - * One of the SSLv3/TLS message types. - */ - len = ((byte3 & 0xff) << 8) + (byte4 & 0xff) + 5; // SSLv3 record header - - } else { - /* - * Must be SSLv2 or something unknown. - * Check if it's short (2 bytes) or - * long (3) header. - * - * Internals can warn about unsupported SSLv2 - */ - boolean isShort = ((byte0 & 0x80) != 0); - - if (isShort && ((byte2 == 1) || byte2 == 4)) { - - final byte major = byte3; - final byte minor = byte4; - final int v = (major << 8) | minor & 0xff; - - // Check if too old (currently not possible) - // or if the major version does not match. - // The actual version negotiation is in the handshaker classes - if ((v < 0x0300) || (major > 0x03)) { - // if it's not SSLv2, we're out of here. - if (v != 0x0002) throw new SSLException("Unsupported record version major=" + major + " minor=" + minor); - } - - /* - * Client or Server Hello - */ - int mask = 0x7f; - len = ((byte0 & mask) << 8) + (byte1 & 0xff) + (2); - } else { - // Gobblygook! - throw new SSLException("Unrecognized SSL message, plaintext connection?"); - } - } - - return len; - } -} diff --git a/src/com/wentch/redkale/net/Server.java b/src/com/wentch/redkale/net/Server.java deleted file mode 100644 index bd61cbb30..000000000 --- a/src/com/wentch/redkale/net/Server.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import com.wentch.redkale.util.*; -import com.wentch.redkale.watch.*; -import java.io.*; -import java.lang.reflect.*; -import java.net.*; -import java.nio.charset.*; -import java.text.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import java.util.logging.*; - -/** - * - * @author zhangjx - */ -public abstract class Server { - - public static final String RESNAME_ROOT = "SER_ROOT"; - - protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName()); - - //------------------------------------------------------------- - protected final long serverStartTime; - - protected final WatchFactory watch; - - protected final String protocol; - - protected final PrepareServlet prepare; - - protected AnyValue config; - - protected Charset charset; - - protected InetSocketAddress address; - - protected Context context; - - protected int backlog; - - protected ProtocolServer serverChannel; - - protected int capacity; - - protected int threads; - - protected ExecutorService executor; - - protected int bufferPoolSize; - - protected int responsePoolSize; - - protected int maxbody; - - protected int readTimeoutSecond; - - protected int writeTimeoutSecond; - - private ScheduledThreadPoolExecutor scheduler; - - protected Server(long serverStartTime, String protocol, PrepareServlet servlet, final WatchFactory watch) { - this.serverStartTime = serverStartTime; - this.protocol = protocol; - this.prepare = servlet; - this.watch = watch; - } - - public void init(final AnyValue config) throws Exception { - Objects.requireNonNull(config); - this.config = config; - this.address = new InetSocketAddress(config.getValue("host", "0.0.0.0"), config.getIntValue("port", 80)); - this.charset = Charset.forName(config.getValue("charset", "UTF-8")); - this.backlog = config.getIntValue("backlog", 8 * 1024); - this.readTimeoutSecond = config.getIntValue("readTimeoutSecond", 0); - this.writeTimeoutSecond = config.getIntValue("writeTimeoutSecond", 0); - this.capacity = config.getIntValue("capacity", 8 * 1024); - this.maxbody = config.getIntValue("maxbody", 64 * 1024); - this.threads = config.getIntValue("threads", Runtime.getRuntime().availableProcessors() * 16); - this.bufferPoolSize = config.getIntValue("bufferPoolSize", Runtime.getRuntime().availableProcessors() * 512); - this.responsePoolSize = config.getIntValue("responsePoolSize", Runtime.getRuntime().availableProcessors() * 256); - final int port = this.address.getPort(); - final AtomicInteger counter = new AtomicInteger(); - final Format f = createFormat(); - this.executor = Executors.newFixedThreadPool(threads, (Runnable r) -> { - Thread t = new WorkThread(executor, r); - t.setName("Servlet-" + protocol + "-" + port + "-Thread-" + f.format(counter.incrementAndGet())); - return t; - }); - } - - public void destroy(final AnyValue config) throws Exception { - this.prepare.destroy(context, config); - if (scheduler != null) scheduler.shutdownNow(); - } - - public InetSocketAddress getSocketAddress() { - return address; - } - - public String getProtocol() { - return protocol; - } - - public Logger getLogger() { - return this.logger; - } - - public void start() throws IOException { - this.context = this.createContext(); - this.prepare.init(this.context, config); - if (this.watch != null) this.watch.inject(this.prepare); - this.serverChannel = ProtocolServer.create(this.protocol, context); - this.serverChannel.open(); - if (this.serverChannel.supportedOptions().contains(StandardSocketOptions.TCP_NODELAY)) { - this.serverChannel.setOption(StandardSocketOptions.TCP_NODELAY, true); - } - serverChannel.bind(address, backlog); - serverChannel.accept(); - final String threadName = "[" + Thread.currentThread().getName() + "] "; - logger.info(threadName + this.getClass().getSimpleName() + "." + protocol + " listen: " + address - + ", threads: " + threads + ", bufferCapacity: " + capacity + ", bufferPoolSize: " + bufferPoolSize + ", responsePoolSize: " + responsePoolSize - + ", started in " + (System.currentTimeMillis() - context.getServerStartTime()) + " ms"); - } - - protected abstract Context createContext(); - - public void shutdown() throws IOException { - long s = System.currentTimeMillis(); - logger.info(this.getClass().getSimpleName() + "-" + this.protocol + " shutdowning"); - try { - this.serverChannel.close(); - } catch (Exception e) { - } - logger.info(this.getClass().getSimpleName() + "-" + this.protocol + " shutdow prepare servlet"); - this.prepare.destroy(this.context, config); - long e = System.currentTimeMillis() - s; - logger.info(this.getClass().getSimpleName() + " shutdown in " + e + " ms"); - } - - protected Format createFormat() { - String sf = "0"; - if (this.threads > 10) sf = "00"; - if (this.threads > 100) sf = "000"; - if (this.threads > 1000) sf = "0000"; - return new DecimalFormat(sf); - } - - public static void loadLib(final Logger logger, final String lib) throws Exception { - if (lib == null || lib.isEmpty()) return; - final Set set = new HashSet<>(); - for (String s : lib.split(";")) { - if (s.isEmpty()) continue; - if (s.endsWith("*")) { - File root = new File(s.substring(0, s.length() - 1)); - if (root.isDirectory()) { - for (File f : root.listFiles()) { - set.add(f.toURI().toURL()); - } - } - } else { - File f = new File(s); - if (f.canRead()) set.add(f.toURI().toURL()); - } - } - if (set.isEmpty()) return; - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - if (cl instanceof URLClassLoader) { - URLClassLoader loader = (URLClassLoader) cl; - final Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); - method.setAccessible(true); - for (URL url : set) { - method.invoke(loader, url); - //if (logger != null) logger.log(Level.INFO, "Server found ClassPath({0})", url); - } - } else { - Thread.currentThread().setContextClassLoader(new URLClassLoader(set.toArray(new URL[set.size()]), cl)); - } - } - -} diff --git a/src/com/wentch/redkale/net/Servlet.java b/src/com/wentch/redkale/net/Servlet.java deleted file mode 100644 index 4bb97ff39..000000000 --- a/src/com/wentch/redkale/net/Servlet.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import com.wentch.redkale.util.AnyValue; -import java.io.IOException; - -/** - * - * @author zhangjx - * @param - * @param

- */ -public interface Servlet> { - - default void init(Context context, AnyValue config) { - } - - public void execute(R request, P response) throws IOException; - - default void destroy(Context context, AnyValue config) { - } - -} diff --git a/src/com/wentch/redkale/net/Transport.java b/src/com/wentch/redkale/net/Transport.java deleted file mode 100644 index d3a87fe01..000000000 --- a/src/com/wentch/redkale/net/Transport.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import com.wentch.redkale.util.*; -import com.wentch.redkale.watch.*; -import java.net.*; -import java.nio.*; -import java.nio.channels.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import java.util.function.*; - -/** - * 传输客户端 - * - * @author zhangjx - */ -public final class Transport { - - public static final String DEFAULT_PROTOCOL = "TCP"; - - protected static final int MAX_POOL_LIMIT = Runtime.getRuntime().availableProcessors() * 16; - - protected static final boolean supportTcpNoDelay; - - static { - boolean tcpNoDelay = false; - try { - AsynchronousSocketChannel channel = AsynchronousSocketChannel.open(); - tcpNoDelay = channel.supportedOptions().contains(StandardSocketOptions.TCP_NODELAY); - channel.close(); - } catch (Exception e) { - } - supportTcpNoDelay = tcpNoDelay; - } - - protected final String name; - - protected final int bufferPoolSize; - - protected final int bufferCapacity; - - protected final boolean tcp; - - protected final String protocol; - - protected final AsynchronousChannelGroup group; - - protected final InetSocketAddress[] remoteAddres; - - protected final ObjectPool bufferPool; - - protected final ConcurrentHashMap> connPool = new ConcurrentHashMap<>(); - - public Transport(Transport transport, InetSocketAddress localAddress, Collection transports) { - this(transport.name, transport.protocol, null, transport.bufferPoolSize, parse(localAddress, transports)); - } - - public Transport(String name, WatchFactory watch, int bufferPoolSize, Collection addresses) { - this(name, DEFAULT_PROTOCOL, watch, bufferPoolSize, addresses); - } - - public Transport(String name, String protocol, WatchFactory watch, int bufferPoolSize, Collection addresses) { - this.name = name; - this.protocol = protocol; - this.tcp = "TCP".equalsIgnoreCase(protocol); - this.bufferPoolSize = bufferPoolSize; - this.bufferCapacity = 8192; - AsynchronousChannelGroup g = null; - try { - final AtomicInteger counter = new AtomicInteger(); - ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 8, (Runnable r) -> { - Thread t = new Thread(r); - t.setDaemon(true); - t.setName("Transport-" + name + "-Thread-" + counter.incrementAndGet()); - return t; - }); - g = AsynchronousChannelGroup.withCachedThreadPool(executor, 1); - } catch (Exception e) { - throw new RuntimeException(e); - } - this.group = g; - AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber(Transport.class.getSimpleName() + "-" + name + "-" + protocol + ".Buffer.creatCounter"); - AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber(Transport.class.getSimpleName() + "-" + name + "-" + protocol + ".Buffer.cycleCounter"); - final int rcapacity = bufferCapacity; - this.bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, bufferPoolSize, - (Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> { - if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false; - e.clear(); - return true; - }); - this.remoteAddres = addresses.toArray(new InetSocketAddress[addresses.size()]); - } - - private static Collection parse(InetSocketAddress addr, Collection transports) { - final Set set = new LinkedHashSet<>(); - for (Transport t : transports) { - set.addAll(Arrays.asList(t.remoteAddres)); - } - set.remove(addr); - return set; - } - - public void close() { - connPool.forEach((k, v) -> v.forEach(c -> c.dispose())); - } - - public boolean match(Collection addrs) { - if (addrs == null) return false; - if (addrs.size() != this.remoteAddres.length) return false; - for (InetSocketAddress addr : this.remoteAddres) { - if (!addrs.contains(addr)) return false; - } - return true; - } - - public InetSocketAddress[] getRemoteAddress() { - return remoteAddres; - } - - @Override - public String toString() { - return Transport.class.getSimpleName() + "{name=" + name + ",protocol=" + protocol + ",remoteAddres=" + Arrays.toString(remoteAddres) + "}"; - } - - public int getBufferCapacity() { - return bufferCapacity; - } - - public ByteBuffer pollBuffer() { - return bufferPool.get(); - } - - public Supplier getBufferSupplier() { - return bufferPool; - } - - public void offerBuffer(ByteBuffer buffer) { - bufferPool.offer(buffer); - } - - public void offerBuffer(ByteBuffer... buffers) { - for (ByteBuffer buffer : buffers) offerBuffer(buffer); - } - - public boolean isTCP() { - return tcp; - } - - public AsyncConnection pollConnection(SocketAddress addr) { - if (addr == null && remoteAddres.length == 1) addr = remoteAddres[0]; - final boolean rand = addr == null; - if (rand && remoteAddres.length < 1) throw new RuntimeException("Transport (" + this.name + ") has no remoteAddress list"); - try { - if (tcp) { - AsynchronousSocketChannel channel = null; - if (rand) { //取地址 - for (int i = 0; i < remoteAddres.length; i++) { - addr = remoteAddres[i]; - BlockingQueue queue = connPool.get(addr); - if (queue != null && !queue.isEmpty()) { - AsyncConnection conn; - while ((conn = queue.poll()) != null) { - if (conn.isOpen()) return conn; - } - } - if (channel == null) { - channel = AsynchronousSocketChannel.open(group); - if (supportTcpNoDelay) channel.setOption(StandardSocketOptions.TCP_NODELAY, true); - } - try { - channel.connect(addr).get(2, TimeUnit.SECONDS); - break; - } catch (Exception iex) { - iex.printStackTrace(); - if (i == remoteAddres.length - 1) channel = null; - } - } - } else { - channel = AsynchronousSocketChannel.open(group); - if (supportTcpNoDelay) channel.setOption(StandardSocketOptions.TCP_NODELAY, true); - channel.connect(addr).get(2, TimeUnit.SECONDS); - } - if (channel == null) return null; - return AsyncConnection.create(channel, addr, 3000, 3000); - } else { // UDP - if (rand) addr = remoteAddres[0]; - DatagramChannel channel = DatagramChannel.open(); - channel.configureBlocking(true); - channel.connect(addr); - return AsyncConnection.create(channel, addr, true, 3000, 3000); -// AsyncDatagramChannel channel = AsyncDatagramChannel.open(group); -// channel.connect(addr); -// return AsyncConnection.create(channel, addr, true, 3000, 3000); - } - } catch (Exception ex) { - throw new RuntimeException("transport address = " + addr, ex); - } - } - - public void offerConnection(final boolean forceClose, AsyncConnection conn) { - if (!forceClose && conn.isTCP()) { //暂时每次都关闭 - if (conn.isOpen()) { - BlockingQueue queue = connPool.get(conn.getRemoteAddress()); - if (queue == null) { - queue = new ArrayBlockingQueue<>(MAX_POOL_LIMIT); - connPool.put(conn.getRemoteAddress(), queue); - } - if (!queue.offer(conn)) conn.dispose(); - } - } else { - conn.dispose(); - } - } - - public void async(SocketAddress addr, final ByteBuffer buffer, A att, final CompletionHandler handler) { - final AsyncConnection conn = pollConnection(addr); - conn.write(buffer, buffer, new CompletionHandler() { - - @Override - public void completed(Integer result, ByteBuffer attachment) { - buffer.clear(); - conn.read(buffer, buffer, new CompletionHandler() { - - @Override - public void completed(Integer result, ByteBuffer attachment) { - if (handler != null) handler.completed(result, att); - offerBuffer(buffer); - offerConnection(false, conn); - } - - @Override - public void failed(Throwable exc, ByteBuffer attachment) { - offerBuffer(buffer); - offerConnection(true, conn); - } - }); - - } - - @Override - public void failed(Throwable exc, ByteBuffer attachment) { - offerBuffer(buffer); - offerConnection(true, conn); - } - }); - } - -} diff --git a/src/com/wentch/redkale/net/WorkThread.java b/src/com/wentch/redkale/net/WorkThread.java deleted file mode 100644 index d88e15b10..000000000 --- a/src/com/wentch/redkale/net/WorkThread.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net; - -import java.util.concurrent.*; - -/** - * - * @author zhangjx - */ -public class WorkThread extends Thread { - - private final ExecutorService executor; - - public WorkThread(ExecutorService executor, Runnable runner) { - super(runner); - this.executor = executor; - this.setDaemon(true); - } - - public void submit(Runnable runner) { - executor.submit(runner); - } - - public ExecutorService getExecutor() { - return executor; - } -} diff --git a/src/com/wentch/redkale/net/http/AuthIgnore.java b/src/com/wentch/redkale/net/http/AuthIgnore.java deleted file mode 100644 index fc95f8774..000000000 --- a/src/com/wentch/redkale/net/http/AuthIgnore.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({METHOD, TYPE}) -@Retention(RUNTIME) -public @interface AuthIgnore { - -} diff --git a/src/com/wentch/redkale/net/http/BasedHttpServlet.java b/src/com/wentch/redkale/net/http/BasedHttpServlet.java deleted file mode 100644 index 0646ae127..000000000 --- a/src/com/wentch/redkale/net/http/BasedHttpServlet.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.net.Response; -import com.wentch.redkale.net.Request; -import com.wentch.redkale.net.Context; -import com.wentch.redkale.util.AnyValue; -import java.io.IOException; -import java.lang.reflect.Method; -import java.nio.*; -import java.util.*; -import java.util.concurrent.*; -import jdk.internal.org.objectweb.asm.*; -import static jdk.internal.org.objectweb.asm.Opcodes.*; - -/** - * - * @author zhangjx - */ -public abstract class BasedHttpServlet extends HttpServlet { - - private Map.Entry[] actions; - - public boolean preExecute(HttpRequest request, HttpResponse response) throws IOException { - return true; - } - - @Override - public final void execute(HttpRequest request, HttpResponse response) throws IOException { - if (!preExecute(request, response)) return; - for (Map.Entry en : actions) { - if (request.getRequestURI().startsWith(en.getKey())) { - Entry entry = en.getValue(); - if (entry.ignore || authenticate(entry.moduleid, entry.actionid, request, response)) { - if (entry.cachetimeout > 0) {//有缓存设置 - CacheEntry ce = entry.cache.get(request.getRequestURI()); - if (ce != null && ce.time + entry.cachetimeout > System.currentTimeMillis()) { //缓存有效 - response.setStatus(ce.status); - response.setContentType(ce.contentType); - response.finish(ce.getBuffers()); - return; - } - response.setInterceptor(entry.cacheInterceptor); - } - entry.servlet.execute(request, response); - } - return; - } - } - throw new IOException(this.getClass().getName() + " not found method for URI(" + request.getRequestURI() + ")"); - } - - @Override - public void init(Context context, AnyValue config) { - String path = ((HttpContext) context).getContextPath(); - WebServlet ws = this.getClass().getAnnotation(WebServlet.class); - if (ws != null && !ws.fillurl()) path = ""; - HashMap map = load(); - this.actions = new Map.Entry[map.size()]; - int i = -1; - for (Map.Entry en : map.entrySet()) { - actions[++i] = new AbstractMap.SimpleEntry<>(path + en.getKey(), en.getValue()); - } - } - - public abstract boolean authenticate(int module, int actionid, HttpRequest request, HttpResponse response) throws IOException; - - private HashMap load() { - final boolean typeIgnore = this.getClass().getAnnotation(AuthIgnore.class) != null; - WebServlet module = this.getClass().getAnnotation(WebServlet.class); - final int serviceid = module == null ? 0 : module.moduleid(); - final HashMap map = new HashMap<>(); - Set nameset = new HashSet<>(); - for (final Method method : this.getClass().getMethods()) { - //----------------------------------------------- - String methodname = method.getName(); - if ("service".equals(methodname) || "preExecute".equals(methodname) || "execute".equals(methodname) || "authenticate".equals(methodname)) continue; - //----------------------------------------------- - Class[] paramTypes = method.getParameterTypes(); - if (paramTypes.length != 2 || paramTypes[0] != HttpRequest.class - || paramTypes[1] != HttpResponse.class) continue; - //----------------------------------------------- - Class[] exps = method.getExceptionTypes(); - if (exps.length > 0 && (exps.length != 1 || exps[0] != IOException.class)) continue; - //----------------------------------------------- - String name = methodname; - int actionid = 0; - WebAction action = method.getAnnotation(WebAction.class); - if (action != null) { - actionid = action.actionid(); - name = action.url().trim(); - } - if (nameset.contains(name)) throw new RuntimeException(this.getClass().getSimpleName() + " has two same " + WebAction.class.getSimpleName() + "(" + name + ")"); - for (String n : nameset) { - if (n.contains(name) || name.contains(n)) { - throw new RuntimeException(this.getClass().getSimpleName() + " has two overlap " + WebAction.class.getSimpleName() + "(" + name + ", " + n + ")"); - } - } - nameset.add(name); - map.put(name, new Entry(typeIgnore, serviceid, actionid, name, method, createHttpServlet(method))); - } - return map; - } - - private HttpServlet createHttpServlet(final Method method) { - //------------------------------------------------------------------------------ - final String supDynName = HttpServlet.class.getName().replace('.', '/'); - final String interName = this.getClass().getName().replace('.', '/'); - final String interDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(this.getClass()); - final String requestSupDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(Request.class); - final String responseSupDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(Response.class); - final String requestDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(HttpRequest.class); - final String responseDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(HttpResponse.class); - String newDynName = interName + "_Dyn_" + method.getName(); - int i = 0; - for (;;) { - try { - Class.forName(newDynName.replace('/', '.')); - newDynName += "_" + (++i); - } catch (Exception ex) { - break; - } - } - //------------------------------------------------------------------------------ - ClassWriter cw = new ClassWriter(0); - FieldVisitor fv; - MethodVisitor mv; - AnnotationVisitor av0; - final String factfield = "factServlet"; - cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null); - { - fv = cw.visitField(ACC_PUBLIC, factfield, interDesc, null, null); - fv.visitEnd(); - } - { //构造函数 - mv = (cw.visitMethod(ACC_PUBLIC, "", "()V", null, null)); - //mv.setDebug(true); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, supDynName, "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - { - mv = (cw.visitMethod(ACC_PUBLIC, "execute", "(" + requestDesc + responseDesc + ")V", null, new String[]{"java/io/IOException"})); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, factfield, interDesc); - mv.visitVarInsn(ALOAD, 1); - mv.visitVarInsn(ALOAD, 2); - mv.visitMethodInsn(INVOKEVIRTUAL, interName, method.getName(), "(" + requestDesc + responseDesc + ")V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(3, 3); - mv.visitEnd(); - } - { - mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "execute", "(" + requestSupDesc + responseSupDesc + ")V", null, new String[]{"java/io/IOException"}); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 1); - mv.visitTypeInsn(CHECKCAST, HttpRequest.class.getName().replace('.', '/')); - mv.visitVarInsn(ALOAD, 2); - mv.visitTypeInsn(CHECKCAST, HttpResponse.class.getName().replace('.', '/')); - mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "execute", "(" + requestDesc + responseDesc + ")V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(3, 3); - mv.visitEnd(); - } - cw.visitEnd(); - //------------------------------------------------------------------------------ - byte[] bytes = cw.toByteArray(); - Class newClazz = new ClassLoader(this.getClass().getClassLoader()) { - public final Class loadClass(String name, byte[] b) { - return defineClass(name, b, 0, b.length); - } - }.loadClass(newDynName.replace('/', '.'), bytes); - try { - HttpServlet instance = (HttpServlet) newClazz.newInstance(); - instance.getClass().getField(factfield).set(instance, this); - return instance; - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - private static final class Entry { - - public Entry(boolean typeIgnore, int moduleid, int actionid, String name, Method method, HttpServlet servlet) { - this.moduleid = moduleid; - this.actionid = actionid; - this.name = name; - this.method = method; - this.servlet = servlet; - this.ignore = typeIgnore || method.getAnnotation(AuthIgnore.class) != null; - HttpCacheable hc = method.getAnnotation(HttpCacheable.class); - this.cachetimeout = hc == null ? 0 : hc.timeout() * 1000; - this.cache = cachetimeout > 0 ? new ConcurrentHashMap() : null; - this.cacheInterceptor = cachetimeout > 0 ? (HttpResponse response, ByteBuffer[] buffers) -> { - int status = response.getStatus(); - if (status != 200) return null; - CacheEntry ce = new CacheEntry(response.getStatus(), response.getContentType(), buffers); - cache.put(response.getRequest().getRequestURI(), ce); - return ce.getBuffers(); - } : null; - } - - public boolean isNeedCheck() { - return this.moduleid != 0 || this.actionid != 0; - } - - public final HttpResponse.Interceptor cacheInterceptor; - - public final ConcurrentHashMap cache; - - public final int cachetimeout; - - public final boolean ignore; - - public final int moduleid; - - public final int actionid; - - public final String name; - - public final Method method; - - public final HttpServlet servlet; - } - - private static final class CacheEntry { - - public final long time = System.currentTimeMillis(); - - private final ByteBuffer[] buffers; - - private final int status; - - private final String contentType; - - public CacheEntry(int status, String contentType, ByteBuffer[] bufs) { - this.status = status; - this.contentType = contentType; - final ByteBuffer[] newBuffers = new ByteBuffer[bufs.length]; - for (int i = 0; i < newBuffers.length; i++) { - newBuffers[i] = bufs[i].duplicate().asReadOnlyBuffer(); - } - this.buffers = newBuffers; - } - - public ByteBuffer[] getBuffers() { - final ByteBuffer[] newBuffers = new ByteBuffer[buffers.length]; - for (int i = 0; i < newBuffers.length; i++) { - newBuffers[i] = buffers[i].duplicate(); - } - return newBuffers; - } - } -} diff --git a/src/com/wentch/redkale/net/http/HttpCacheable.java b/src/com/wentch/redkale/net/http/HttpCacheable.java deleted file mode 100644 index 6c2010381..000000000 --- a/src/com/wentch/redkale/net/http/HttpCacheable.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import java.lang.annotation.*; - -/** - * - * @author zhangjx - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface HttpCacheable { - - /** - * 超时的秒数 - * - * @return - */ - int timeout() default 15; -} diff --git a/src/com/wentch/redkale/net/http/HttpContext.java b/src/com/wentch/redkale/net/http/HttpContext.java deleted file mode 100644 index 292daa440..000000000 --- a/src/com/wentch/redkale/net/http/HttpContext.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.net.*; -import com.wentch.redkale.util.*; -import com.wentch.redkale.watch.*; -import java.net.*; -import java.nio.*; -import java.nio.charset.*; -import java.security.*; -import java.util.concurrent.*; -import java.util.logging.*; - -/** - * - * @author zhangjx - */ -public final class HttpContext extends Context { - - protected final String contextPath; - - protected final SecureRandom random = new SecureRandom(); - - public HttpContext(long serverStartTime, Logger logger, ExecutorService executor, int bufferCapacity, ObjectPool bufferPool, - ObjectPool responsePool, int maxbody, Charset charset, InetSocketAddress address, PrepareServlet prepare, - WatchFactory watch, int readTimeoutSecond, int writeTimeoutSecond, String contextPath) { - super(serverStartTime, logger, executor, bufferCapacity, bufferPool, responsePool, maxbody, charset, - address, prepare, watch, readTimeoutSecond, writeTimeoutSecond); - this.contextPath = contextPath; - random.setSeed(Math.abs(System.nanoTime())); - } - - public String getContextPath() { - return this.contextPath; - } - - protected String createSessionid() { - byte[] bytes = new byte[16]; - random.nextBytes(bytes); - return new String(Utility.binToHex(bytes)); - } - - protected WatchFactory getWatchFactory() { - return watch; - } - - protected ExecutorService getExecutor() { - return executor; - } - - protected ObjectPool getResponsePool() { - return responsePool; - } - -} diff --git a/src/com/wentch/redkale/net/http/HttpPrepareServlet.java b/src/com/wentch/redkale/net/http/HttpPrepareServlet.java deleted file mode 100644 index 00828d9aa..000000000 --- a/src/com/wentch/redkale/net/http/HttpPrepareServlet.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.net.*; -import com.wentch.redkale.util.*; -import com.wentch.redkale.util.AnyValue.DefaultAnyValue; -import com.wentch.redkale.watch.*; -import java.io.*; -import java.nio.*; -import java.util.*; -import java.util.AbstractMap.SimpleEntry; -import java.util.function.*; -import java.util.logging.*; -import java.util.regex.*; - -/** - * - * @author zhangjx - */ -public final class HttpPrepareServlet extends PrepareServlet> { - - private ByteBuffer flashPolicyBuffer; - - private final List servlets = new ArrayList<>(); - - private final Map strmaps = new HashMap<>(); - - private SimpleEntry, HttpServlet>[] regArray = new SimpleEntry[0]; - - private HttpServlet resourceHttpServlet = new HttpResourceServlet(); - - private String flashdomain = "*"; - - private String flashports = "80,443,$"; - - @Override - public void init(Context context, AnyValue config) { - this.servlets.stream().forEach(s -> { - s.init(context, s.conf); - }); - final WatchFactory watch = ((HttpContext) context).getWatchFactory(); - if (watch != null) { - this.servlets.stream().forEach(s -> { - watch.inject(s); - }); - } - if (config != null) { - AnyValue ssConfig = config.getAnyValue("servlets"); - if (ssConfig != null) { - AnyValue resConfig = ssConfig.getAnyValue("resource-servlet"); - if (resConfig instanceof DefaultAnyValue) { - if (resConfig.getValue("webroot") == null) - ((DefaultAnyValue) resConfig).addValue("webroot", config.getValue("root")); - } - if (resConfig == null) { - DefaultAnyValue dresConfig = new DefaultAnyValue(); - dresConfig.addValue("webroot", config.getValue("root")); - resConfig = dresConfig; - } - this.resourceHttpServlet.init(context, resConfig); - } - this.flashdomain = config.getValue("crossdomain-domain", "*"); - this.flashports = config.getValue("crossdomain-ports", "80,443,$"); - } - } - - @Override - public void execute(HttpRequest request, HttpResponse response) throws IOException { - try { - if (request.flashPolicy) { - response.skipHeader(); - if (flashPolicyBuffer == null) { - flashPolicyBuffer = ByteBuffer.wrap(("" - + "" - + "" - + "").getBytes()).asReadOnlyBuffer(); - } - response.finish(true, flashPolicyBuffer.duplicate()); - return; - } - final String uri = request.getRequestURI(); - HttpServlet servlet = this.strmaps.isEmpty() ? null : this.strmaps.get(uri); - if (servlet == null && this.regArray != null) { - for (SimpleEntry, HttpServlet> en : regArray) { - if (en.getKey().test(uri)) { - servlet = en.getValue(); - break; - } - } - } - if (servlet == null) servlet = this.resourceHttpServlet; - servlet.execute(request, response); - } catch (Exception e) { - request.getContext().getLogger().log(Level.WARNING, "Servlet occur, forece to close channel. request = " + request, e); - response.finish(500, null); - } - } - - public void addHttpServlet(HttpServlet servlet, AnyValue conf, String... mappings) { - for (String mapping : mappings) { - if (contains(mapping, '.', '*', '{', '[', '(', '|', '^', '$', '+', '?', '\\')) { //是否是正则表达式)) - if (mapping.charAt(0) != '^') mapping = '^' + mapping; - if (mapping.endsWith("/*")) { - mapping = mapping.substring(0, mapping.length() - 1) + ".*"; - } else { - mapping += "$"; - } - if (regArray == null) { - regArray = new SimpleEntry[1]; - regArray[0] = new SimpleEntry<>(Pattern.compile(mapping).asPredicate(), servlet); - } else { - regArray = Arrays.copyOf(regArray, regArray.length + 1); - regArray[regArray.length - 1] = new SimpleEntry<>(Pattern.compile(mapping).asPredicate(), servlet); - } - } else if (mapping != null && !mapping.isEmpty()) { - strmaps.put(mapping, servlet); - } - } - servlet.conf = conf; - this.servlets.add(servlet); - } - - private static boolean contains(String string, char... values) { - if (string == null) return false; - for (char ch : Utility.charArray(string)) { - for (char ch2 : values) { - if (ch == ch2) return true; - } - } - return false; - } - - public void setResourceServlet(HttpServlet servlet) { - if (servlet != null) { - this.resourceHttpServlet = servlet; - } - } - - @Override - public void destroy(Context context, AnyValue config) { - this.resourceHttpServlet.destroy(context, config); - this.servlets.stream().forEach(s -> { - s.destroy(context, s.conf); - }); - } - -} diff --git a/src/com/wentch/redkale/net/http/HttpRequest.java b/src/com/wentch/redkale/net/http/HttpRequest.java deleted file mode 100644 index a39740dc2..000000000 --- a/src/com/wentch/redkale/net/http/HttpRequest.java +++ /dev/null @@ -1,531 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.convert.json.*; -import com.wentch.redkale.util.ByteArray; -import com.wentch.redkale.net.*; -import com.wentch.redkale.util.AnyValue.DefaultAnyValue; -import java.io.*; -import java.net.*; -import java.nio.*; -import java.nio.channels.*; -import java.nio.charset.*; - -/** - * - * @author zhangjx - */ -public class HttpRequest extends Request { - - protected static final Charset UTF8 = Charset.forName("UTF-8"); - - protected static final String SESSIONID_NAME = "JSESSIONID"; - - private static final byte[] flashRequestContent1 = "\0".getBytes(); - - private static final byte[] flashRequestContent2 = "".getBytes(); - - private String method; - - private String protocol; - - protected String requestURI; - - private long contentLength = -1; - - private String contentType; - - private String host; - - private String connection; - - protected String cookiestr; - - private HttpCookie[] cookies; - - protected String newsessionid; - - protected final DefaultAnyValue header = new DefaultAnyValue(); - - protected final DefaultAnyValue params = new DefaultAnyValue(); - - private final ByteArray array = new ByteArray(); - - private boolean bodyparsed = false; - - protected boolean flashPolicy = false; - - protected boolean boundary = false; - - private final String remoteAddrHeader; - - public HttpRequest(Context context, String remoteAddrHeader) { - super(context); - this.remoteAddrHeader = remoteAddrHeader; - } - - protected void setKeepAlive(boolean keepAlive) { - this.keepAlive = keepAlive; - } - - protected boolean isKeepAlive() { - return this.keepAlive; - } - - protected AsyncConnection getChannel() { - return this.channel; - } - - protected JsonConvert getJsonConvert(){ - return this.jsonConvert; - } - - @Override - protected int readHeader(final ByteBuffer buffer) { - if (!readLine(buffer, array)) { - if (array.equal(flashRequestContent1) || array.equal(flashRequestContent2)) { //兼容 flash socket - this.flashPolicy = true; - return 0; - } - return -1; - } - Charset charset = this.context.getCharset(); - int index = 0; - int offset = array.find(index, ' '); - if (offset <= 0) return -1; - this.method = array.toString(index, offset, charset).trim(); - index = ++offset; - offset = array.find(index, ' '); - if (offset <= 0) return -1; - int off = array.find(index, '#'); - if (off > 0) offset = off; - int qst = array.find(index, offset, (byte) '?'); - if (qst > 0) { - this.requestURI = array.toDecodeString(index, qst - index, charset).trim(); - addParameter(array, qst + 1, offset - qst - 1); - } else { - this.requestURI = array.toDecodeString(index, offset - index, charset).trim(); - } - if (this.requestURI.contains("../")) return -1; - index = ++offset; - this.protocol = array.toString(index, array.count() - index, charset).trim(); - while (readLine(buffer, array)) { - if (array.count() < 2) break; - index = 0; - offset = array.find(index, ':'); - if (offset <= 0) return -1; - String name = array.toString(index, offset, charset).trim(); - index = offset + 1; - String value = array.toString(index, array.count() - index, charset).trim(); - switch (name) { - case "Content-Type": - this.contentType = value; - break; - case "Content-Length": - this.contentLength = Long.decode(value); - break; - case "Host": - this.host = value; - break; - case "Cookie": - if (this.cookiestr == null || this.cookiestr.isEmpty()) { - this.cookiestr = value; - } else { - this.cookiestr += ";" + value; - } - break; - case "Connection": - this.connection = value; - this.setKeepAlive(!"close".equalsIgnoreCase(value)); - break; - default: - header.addValue(name, value); - } - } - array.clear(); - if (buffer.hasRemaining()) array.add(buffer, buffer.remaining()); - if (this.contentType != null && this.contentType.contains("boundary=")) { - this.boundary = true; - } - if (this.contentLength > 0 && (this.contentType == null || !this.boundary)) { - if (this.contentLength > context.getMaxbody()) return -1; - int lr = (int) this.contentLength - array.count(); - return lr > 0 ? lr : 0; - } - return 0; - } - - @Override - protected int readBody(ByteBuffer buffer) { - int len = buffer.remaining(); - array.add(buffer, len); - return len; - } - - @Override - protected void prepare() { - } - - private void parseBody() { - if (this.boundary || bodyparsed) return; - addParameter(array, 0, array.count()); - bodyparsed = true; - } - - private void addParameter(final ByteArray array, final int offset, final int len) { - if (len < 1) return; - Charset charset = this.context.getCharset(); - int limit = offset + len; - int keypos = array.find(offset, limit, '='); - int valpos = array.find(offset, limit, '&'); - if (keypos <= 0 || (valpos >= 0 && valpos < keypos)) { - if (valpos > 0) addParameter(array, valpos + 1, limit - valpos - 1); - return; - } - String name = array.toDecodeString(offset, keypos - offset, charset); - ++keypos; - String value = array.toDecodeString(keypos, (valpos < 0) ? (limit - keypos) : (valpos - keypos), charset); - this.params.addValue(name, value); - if (valpos >= 0) { - addParameter(array, valpos + 1, limit - valpos - 1); - } - } - - private boolean readLine(ByteBuffer buffer, ByteArray bytes) { - byte lasted = '\r'; - bytes.clear(); - for (;;) { - if (!buffer.hasRemaining()) { - if (lasted != '\r') bytes.add(lasted); - return false; - } - byte b = buffer.get(); - if (b == -1 || (lasted == '\r' && b == '\n')) break; - if (lasted != '\r') bytes.add(lasted); - lasted = b; - } - return true; - } - - @Override - protected void setProperty(String name, Object value) { - super.setProperty(name, value); - } - - @Override - @SuppressWarnings("unchecked") - protected T getProperty(String name) { - return super.getProperty(name); - } - - @Override - protected void removeProperty(String name) { - super.removeProperty(name); - } - - @Override - public HttpContext getContext() { - return (HttpContext) this.context; - } - - public String getRemoteAddr() { - if (remoteAddrHeader != null) { - String val = getHeader(remoteAddrHeader); - if (val != null) return val; - } - SocketAddress addr = getRemoteAddress(); - if (addr == null) return ""; - if (addr instanceof InetSocketAddress) return ((InetSocketAddress) addr).getAddress().getHostAddress(); - return String.valueOf(addr); - } - - public String getBody(final Charset charset) { - return array.toString(charset); - } - - public String getBody() { - return array.toString(); - } - - public String getBodyUTF8() { - return array.toString(UTF8); - } - - public SocketAddress getRemoteAddress() { - return this.channel.getRemoteAddress(); - } - - @Override - public String toString() { - parseBody(); - return this.getClass().getSimpleName() + "{method:" + this.method + ", requestURI:" + this.requestURI - + ", contentType:" + this.contentType + ", connection:" + this.connection + ", protocol:" + this.protocol - + ", contentLength:" + this.contentLength + ", cookies:" + this.cookiestr - + ", host:" + this.host + ", params:" + this.params + ", header:" + this.header + "}"; - } - - public final MultiContext getMultiContext() { - return new MultiContext(context.getCharset(), this.getContentType(), - new BufferedInputStream(Channels.newInputStream(this.channel), Math.max(array.count(), 8192)) { - { - array.write(this.buf); - this.count = array.count(); - } - }); - } - - @Override - protected void recycle() { - this.cookiestr = null; - this.cookies = null; - this.newsessionid = null; - this.method = null; - this.protocol = null; - this.requestURI = null; - this.contentType = null; - this.host = null; - this.connection = null; - this.contentLength = -1; - this.boundary = false; - this.bodyparsed = false; - this.flashPolicy = false; - - this.header.clear(); - this.params.clear(); - this.array.clear(); - super.recycle(); - } - - public String getSessionid(boolean create) { - String sessionid = getCookie(SESSIONID_NAME, null); - if (create && (sessionid == null || sessionid.isEmpty())) { - sessionid = ((HttpContext) context).createSessionid(); - this.newsessionid = sessionid; - } - return sessionid; - } - - public String changeSessionid() { - this.newsessionid = ((HttpContext) context).createSessionid(); - return newsessionid; - } - - public void invalidateSession() { - this.newsessionid = ""; //为空表示删除sessionid - } - - public HttpCookie[] getCookies() { - if (this.cookies == null) this.cookies = parseCookies(this.cookiestr); - return this.cookies; - } - - public String getCookie(String name) { - return getCookie(name, null); - } - - public String getCookie(String name, String dfvalue) { - for (HttpCookie cookie : getCookies()) { - if (name.equals(cookie.getName())) return cookie.getValue(); - } - return dfvalue; - } - - private static HttpCookie[] parseCookies(String cookiestr) { - if (cookiestr == null || cookiestr.isEmpty()) return new HttpCookie[0]; - String str = cookiestr.replaceAll("(^;)|(;$)", "").replaceAll(";+", ";"); - if (str.isEmpty()) return new HttpCookie[0]; - String[] strs = str.split(";"); - HttpCookie[] cookies = new HttpCookie[strs.length]; - for (int i = 0; i < strs.length; i++) { - String s = strs[i]; - int pos = s.indexOf('='); - String v = (pos < 0 ? "" : s.substring(pos + 1)); - if (v.indexOf('"') == 0 && v.lastIndexOf('"') == v.length() - 1) v = v.substring(1, v.length() - 1); - cookies[i] = new HttpCookie((pos < 0 ? s : s.substring(0, pos)), v); - } - return cookies; - } - - public String getConnection() { - return connection; - } - - public String getMethod() { - return method; - } - - public String getProtocol() { - return protocol; - } - - public String getHost() { - return host; - } - - protected static InetSocketAddress parseSocketAddress(String host) { - if (host == null || host.isEmpty()) return null; - int pos = host.indexOf(':'); - String hostname = pos < 0 ? host : host.substring(0, pos); - int port = pos < 0 ? 80 : Integer.parseInt(host.substring(pos + 1)); - return new InetSocketAddress(hostname, port); - } - - protected InetSocketAddress getHostSocketAddress() { - return parseSocketAddress(host); - } - - /** - * 截取getRequestURI最后的一个/后面的部分 - * - * @return - */ - public String getRequstURILastPath() { - if (requestURI == null) return ""; - return requestURI.substring(requestURI.lastIndexOf('/') + 1); - } - - /** - * - * 从prefix之后截取getRequestURI再对"/"进行分隔 - *

- * @param prefix - * @return - */ - public String[] getRequstURIPaths(String prefix) { - if (requestURI == null || prefix == null) return new String[0]; - return requestURI.substring(requestURI.indexOf(prefix) + prefix.length() + (prefix.endsWith("/") ? 0 : 1)).split("/"); - } - - public String getRequstURIPath(String prefix, String defvalue) { - if (requestURI == null || prefix == null) return defvalue; - int pos = requestURI.indexOf(prefix); - if (pos < 0) return defvalue; - String sub = requestURI.substring(pos + prefix.length()); - pos = sub.indexOf('/'); - return pos < 0 ? sub : sub.substring(0, pos); - } - - public short getRequstURIPath(String prefix, short defvalue) { - String val = getRequstURIPath(prefix, null); - return val == null ? defvalue : Short.parseShort(val); - } - - public int getRequstURIPath(String prefix, int defvalue) { - String val = getRequstURIPath(prefix, null); - return val == null ? defvalue : Integer.parseInt(val); - } - - public long getRequstURIPath(String prefix, long defvalue) { - String val = getRequstURIPath(prefix, null); - return val == null ? defvalue : Long.parseLong(val); - } - - public String getRequestURI() { - return requestURI; - } - - public long getContentLength() { - return contentLength; - } - - public String getContentType() { - return contentType; - } - - //------------------------------------------------------------------------------ - public String[] getHeaderNames() { - return header.getNames(); - } - - public String getHeader(String name) { - return header.getValue(name); - } - - public T getJsonHeader(Class clazz, String name) { - String v = getHeader(name); - return v == null || v.isEmpty() ? null : jsonConvert.convertFrom(clazz, v); - } - - public boolean getBooleanHeader(String name, boolean defaultValue) { - return header.getBoolValue(name, defaultValue); - } - - public short getShortHeader(String name, short defaultValue) { - return header.getShortValue(name, defaultValue); - } - - public int getIntHeader(String name, int defaultValue) { - return header.getIntValue(name, defaultValue); - } - - public long getLongHeader(String name, long defaultValue) { - return header.getLongValue(name, defaultValue); - } - - public float getFloatHeader(String name, float defaultValue) { - return header.getFloatValue(name, defaultValue); - } - - public double getDoubleHeader(String name, double defaultValue) { - return header.getDoubleValue(name, defaultValue); - } - - public String getHeader(String name, String defaultValue) { - return header.getValue(name, defaultValue); - } - - //------------------------------------------------------------------------------ - public String[] getParameterNames() { - parseBody(); - return params.getNames(); - } - - public String getParameter(String name) { - parseBody(); - return params.getValue(name); - } - - public T getJsonParameter(Class clazz, String name) { - String v = getParameter(name); - return v == null || v.isEmpty() ? null : jsonConvert.convertFrom(clazz, v); - } - - public boolean getBooleanParameter(String name, boolean defaultValue) { - parseBody(); - return params.getBoolValue(name, defaultValue); - } - - public short getShortParameter(String name, short defaultValue) { - parseBody(); - return params.getShortValue(name, defaultValue); - } - - public int getIntParameter(String name, int defaultValue) { - parseBody(); - return params.getIntValue(name, defaultValue); - } - - public long getLongParameter(String name, long defaultValue) { - parseBody(); - return params.getLongValue(name, defaultValue); - } - - public float getFloatParameter(String name, float defaultValue) { - parseBody(); - return params.getFloatValue(name, defaultValue); - } - - public double getDoubleParameter(String name, double defaultValue) { - parseBody(); - return params.getDoubleValue(name, defaultValue); - } - - public String getParameter(String name, String defaultValue) { - parseBody(); - return params.getValue(name, defaultValue); - } -} diff --git a/src/com/wentch/redkale/net/http/HttpResourceServlet.java b/src/com/wentch/redkale/net/http/HttpResourceServlet.java deleted file mode 100644 index ac0795efd..000000000 --- a/src/com/wentch/redkale/net/http/HttpResourceServlet.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.net.*; -import com.wentch.redkale.util.*; -import java.io.*; -import java.nio.*; -import java.nio.file.*; -import static java.nio.file.StandardWatchEventKinds.*; -import java.util.*; -import java.util.AbstractMap.SimpleEntry; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import java.util.function.*; -import java.util.logging.*; -import java.util.regex.*; - -/** - * - * @author zhangjx - */ -public final class HttpResourceServlet extends HttpServlet { - - private static final Logger logger = Logger.getLogger(HttpResourceServlet.class.getSimpleName()); - - protected class WatchThread extends Thread { - - protected final File root; - - protected final WatchService watcher; - - public WatchThread(File root) throws IOException { - this.root = root; - this.setName("Servlet-ResourceWatch-Thread"); - this.setDaemon(true); - this.watcher = this.root.toPath().getFileSystem().newWatchService(); - } - - @Override - public void run() { - try { - final String rootstr = root.getCanonicalPath(); - while (!this.isInterrupted()) { - final WatchKey key = watcher.take(); - final Path parent = keymaps.get(key); - if (parent == null) { - key.cancel(); - continue; - } - key.pollEvents().stream().forEach((event) -> { - try { - Path path = parent.resolve((Path) event.context()); - final String uri = path.toString().substring(rootstr.length()).replace('\\', '/'); - //logger.log(Level.FINEST, "file(" + uri + ") happen " + event.kind() + " event"); - if (event.kind() == ENTRY_DELETE) { - files.remove(uri); - } else if (event.kind() == ENTRY_MODIFY) { - FileEntry en = files.get(uri); - if (en != null) { - Thread.sleep(5000L); //等待update file完毕 - en.update(); - } - } - } catch (Exception ex) { - logger.log(Level.FINE, event.context() + " occur erroneous", ex); - } - }); - key.reset(); - } - } catch (Exception e) { - } - } - } - - //缓存总大小, 默认128M - protected long cachelimit = 128 * 1024 * 1024L; - - protected final LongAdder cachedLength = new LongAdder(); - - //最大可缓存的文件大小, 大于该值的文件将不被缓存 - protected long cachelengthmax = 1 * 1024 * 1024; - - protected File root = new File("./root/"); - - protected final ConcurrentHashMap files = new ConcurrentHashMap<>(); - - protected final ConcurrentHashMap keymaps = new ConcurrentHashMap<>(); - - protected SimpleEntry[] locationRewrites; - - protected WatchThread watchThread; - - protected Predicate ranges; - - @Override - public void init(Context context, AnyValue config) { - if (config != null) { - String rootstr = config.getValue("webroot", "root"); - if (rootstr.indexOf(':') < 0 && rootstr.indexOf('/') != 0 && System.getProperty("APP_HOME") != null) { - rootstr = new File(System.getProperty("APP_HOME"), rootstr).getPath(); - } - String rangesValue = config.getValue("ranges"); - this.ranges = rangesValue != null ? Pattern.compile(rangesValue).asPredicate() : null; - try { - this.root = new File(rootstr).getCanonicalFile(); - } catch (IOException ioe) { - this.root = new File(rootstr); - } - AnyValue cacheconf = config.getAnyValue("caches"); - if (cacheconf != null) { - this.cachelimit = parseLenth(cacheconf.getValue("limit"), 128 * 1024 * 1024L); - this.cachelengthmax = parseLenth(cacheconf.getValue("lengthmax"), 1 * 1024 * 1024L); - } - List> locations = new ArrayList<>(); - for (AnyValue av : config.getAnyValues("rewrite")) { - if ("location".equals(av.getValue("type"))) { - String m = av.getValue("match"); - String f = av.getValue("forward"); - if (m != null && f != null) { - locations.add(new SimpleEntry<>(Pattern.compile(m), f)); - } - } - } - this.locationRewrites = locations.isEmpty() ? null : locations.toArray(new SimpleEntry[locations.size()]); - } - if (this.cachelimit < 1) return; //不缓存不需要开启WatchThread监听 - if (this.root != null) { - try { - this.watchThread = new WatchThread(this.root); - this.watchThread.start(); - } catch (IOException ex) { - logger.log(Level.WARNING, HttpResourceServlet.class.getSimpleName() + " start watch-thread error", ex); - } - } - } - - @Override - public void destroy(Context context, AnyValue config) { - if (this.watchThread != null) { - try { - this.watchThread.watcher.close(); - } catch (IOException ex) { - logger.log(Level.WARNING, HttpResourceServlet.class.getSimpleName() + " close watch-thread error", ex); - } - if (this.watchThread.isAlive()) this.watchThread.interrupt(); - } - } - - private static long parseLenth(String value, long defValue) { - if (value == null) return defValue; - value = value.toUpperCase().replace("B", ""); - if (value.endsWith("G")) return Long.decode(value.replace("G", "")) * 1024 * 1024 * 1024; - if (value.endsWith("M")) return Long.decode(value.replace("M", "")) * 1024 * 1024; - if (value.endsWith("K")) return Long.decode(value.replace("K", "")) * 1024; - return Long.decode(value); - } - - @Override - public void execute(HttpRequest request, HttpResponse response) throws IOException { - String uri = request.getRequestURI(); - if (locationRewrites != null) { - for (SimpleEntry entry : locationRewrites) { - Matcher matcher = entry.getKey().matcher(uri); - if (matcher.find()) { - StringBuffer sb = new StringBuffer(uri.length()); - matcher.appendReplacement(sb, entry.getValue()); - matcher.appendTail(sb); - uri = sb.toString(); - break; - } - } - } - if (uri.length() == 0 || uri.equals("/")) uri = "/index.html"; - //System.out.println(request); - FileEntry entry; - if (watchThread == null) { - entry = createFileEntry(uri); - } else { //有缓存 - entry = files.computeIfAbsent(uri, x -> createFileEntry(x)); - } - if (entry == null) { - response.finish404(); - } else { - response.finishFile(entry.file, entry.content); - } - } - - private FileEntry createFileEntry(String uri) { - File file = new File(root, uri); - if (file.isDirectory()) file = new File(file, "index.html"); - if (!file.isFile() || !file.canRead()) return null; - FileEntry en = new FileEntry(this, file); - if (watchThread == null) return en; - try { - Path p = file.getParentFile().toPath(); - keymaps.put(p.register(watchThread.watcher, ENTRY_MODIFY, ENTRY_DELETE), p); - } catch (IOException e) { - logger.log(Level.INFO, HttpResourceServlet.class.getSimpleName() + " watch FileEntry(" + uri + ") erroneous", e); - } - return en; - } - - private static final class FileEntry { - - final File file; - - private final HttpResourceServlet servlet; - - ByteBuffer content; - - public FileEntry(final HttpResourceServlet servlet, File file) { - this.servlet = servlet; - this.file = file; - update(); - } - - public void update() { - if (this.content != null) { - this.servlet.cachedLength.add(0L - this.content.remaining()); - this.content = null; - } - long length = this.file.length(); - if (length > this.servlet.cachelengthmax) return; - if (this.servlet.cachedLength.longValue() + length > this.servlet.cachelimit) return; //超过缓存总容量 - try { - FileInputStream in = new FileInputStream(file); - ByteArrayOutputStream out = new ByteArrayOutputStream((int) file.length()); - byte[] bytes = new byte[10240]; - int pos; - while ((pos = in.read(bytes)) != -1) { - out.write(bytes, 0, pos); - } - in.close(); - byte[] bs = out.toByteArray(); - ByteBuffer buf = ByteBuffer.allocateDirect(bs.length); - buf.put(bs); - buf.flip(); - this.content = buf.asReadOnlyBuffer(); - this.servlet.cachedLength.add(this.content.remaining()); - } catch (Exception e) { - logger.log(Level.INFO, HttpResourceServlet.class.getSimpleName() + " update FileEntry(" + file + ") erroneous", e); - } - } - - @Override - protected void finalize() throws Throwable { - if (this.content != null) this.servlet.cachedLength.add(0L - this.content.remaining()); - super.finalize(); - } - - public long getCachedLength() { - return this.content == null ? 0L : this.content.remaining(); - } - - } -} diff --git a/src/com/wentch/redkale/net/http/HttpResponse.java b/src/com/wentch/redkale/net/http/HttpResponse.java deleted file mode 100644 index 3ef352570..000000000 --- a/src/com/wentch/redkale/net/http/HttpResponse.java +++ /dev/null @@ -1,561 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.net.*; -import com.wentch.redkale.util.*; -import com.wentch.redkale.util.AnyValue.DefaultAnyValue; -import com.wentch.redkale.util.AnyValue.Entry; -import java.io.*; -import java.lang.reflect.*; -import java.net.*; -import java.nio.*; -import java.nio.channels.*; -import java.nio.file.*; -import java.text.*; -import java.util.*; -import java.util.concurrent.atomic.*; - -/** - * - * @author zhangjx - * @param - */ -public class HttpResponse extends Response { - - /** - * HttpResponse.finish 方法内调用 - * - */ - public static interface Interceptor { - - public ByteBuffer[] invoke(final HttpResponse response, final ByteBuffer[] buffers); - } - - private static final ByteBuffer buffer304 = ByteBuffer.wrap("HTTP/1.1 304 Not Modified\r\n\r\n".getBytes()).asReadOnlyBuffer(); - - private static final ByteBuffer buffer404 = ByteBuffer.wrap("HTTP/1.1 404 Not Found\r\nContent-Length:0\r\n\r\n".getBytes()).asReadOnlyBuffer(); - - protected static final byte[] LINE = new byte[]{'\r', '\n'}; - - private static final Set options = new HashSet<>(); - - private static final DateFormat GMT_DATE_FORMAT = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss z", Locale.ENGLISH); - - private static final Map httpCodes = new HashMap<>(); - - static { - options.add(StandardOpenOption.READ); - GMT_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT")); - - httpCodes.put(100, "Continue"); - httpCodes.put(101, "Switching Protocols"); - - httpCodes.put(200, "OK"); - httpCodes.put(201, "Created"); - httpCodes.put(202, "Accepted"); - httpCodes.put(203, "Non-Authoritative Information"); - httpCodes.put(204, "No Content"); - httpCodes.put(205, "Reset Content"); - httpCodes.put(206, "Partial Content"); - - httpCodes.put(300, "Multiple Choices"); - httpCodes.put(301, "Moved Permanently"); - httpCodes.put(302, "Found"); - httpCodes.put(303, "See Other"); - httpCodes.put(304, "Not Modified"); - httpCodes.put(305, "Use Proxy"); - httpCodes.put(307, "Temporary Redirect"); - - httpCodes.put(400, "Bad Request"); - httpCodes.put(401, "Unauthorized"); - httpCodes.put(402, "Payment Required"); - httpCodes.put(403, "Forbidden"); - httpCodes.put(404, "Not Found"); - httpCodes.put(405, "Method Not Allowed"); - httpCodes.put(406, "Not Acceptable"); - httpCodes.put(407, "Proxy Authentication Required"); - httpCodes.put(408, "Request Timeout"); - httpCodes.put(409, "Conflict"); - httpCodes.put(410, "Gone"); - httpCodes.put(411, "Length Required"); - httpCodes.put(412, "Precondition Failed"); - httpCodes.put(413, "Request Entity Too Large"); - httpCodes.put(414, "Request URI Too Long"); - httpCodes.put(415, "Unsupported Media Type"); - httpCodes.put(416, "Requested Range Not Satisfiable"); - httpCodes.put(417, "Expectation Failed"); - - httpCodes.put(500, "Internal Server Error"); - httpCodes.put(501, "Not Implemented"); - httpCodes.put(502, "Bad Gateway"); - httpCodes.put(503, "Service Unavailable"); - httpCodes.put(504, "Gateway Timeout"); - httpCodes.put(505, "HTTP Version Not Supported"); - } - - private int status = 200; - - private String contentType = "text/plain; charset=utf-8"; - - private long contentLength = -1; - - private HttpCookie[] cookies; - - private boolean headsended = false; - - private Interceptor interceptor; - //------------------------------------------------ - - private final DefaultAnyValue header = new DefaultAnyValue(); - - private final String[][] defaultAddHeaders; - - private final String[][] defaultSetHeaders; - - private final HttpCookie defcookie; - - public static ObjectPool createPool(AtomicLong creatCounter, AtomicLong cycleCounter, int max, Creator creator) { - return new ObjectPool<>(creatCounter, cycleCounter, max, creator, (x) -> ((HttpResponse) x).prepare(), (x) -> ((HttpResponse) x).recycle()); - } - - public HttpResponse(Context context, R request, String[][] defaultAddHeaders, String[][] defaultSetHeaders, HttpCookie defcookie) { - super(context, request); - this.defaultAddHeaders = defaultAddHeaders; - this.defaultSetHeaders = defaultSetHeaders; - this.defcookie = defcookie; - } - - @Override - protected AsyncConnection removeChannel() { - return super.removeChannel(); - } - - @Override - protected boolean recycle() { - this.status = 200; - this.contentLength = -1; - this.contentType = null; - this.cookies = null; - this.headsended = false; - this.header.clear(); - this.interceptor = null; - return super.recycle(); - } - - @Override - protected void init(AsyncConnection channel) { - super.init(channel); - } - - protected String getHttpCode(int status) { - return httpCodes.get(status); - } - - protected HttpRequest getRequest() { - return request; - } - - protected String getHttpCode(int status, String defValue) { - String v = httpCodes.get(status); - return v == null ? defValue : v; - } - - @Override - public HttpContext getContext() { - return (HttpContext) context; - } - - public void addCookie(HttpCookie... cookies) { - if (this.cookies == null) { - this.cookies = cookies; - } else { - HttpCookie[] news = new HttpCookie[this.cookies.length + cookies.length]; - System.arraycopy(this.cookies, 0, news, 0, this.cookies.length); - System.arraycopy(cookies, 0, news, this.cookies.length, cookies.length); - this.cookies = news; - } - } - - public void finishJson(Object obj) { - this.contentType = "text/plain; charset=utf-8"; - finish(request.getJsonConvert().convertTo(context.getCharset(), context.getBufferSupplier(), obj)); - } - - public void finishJson(Type type, Object obj) { - this.contentType = "text/plain; charset=utf-8"; - finish(request.getJsonConvert().convertTo(context.getCharset(), context.getBufferSupplier(), type, obj)); - } - - public void finishJson(Object... objs) { - this.contentType = "text/plain; charset=utf-8"; - finish(request.getJsonConvert().convertTo(context.getCharset(), context.getBufferSupplier(), objs)); - } - - public void finish(String obj) { - if (obj == null || obj.isEmpty()) { - final ByteBuffer headbuf = createHeader(); - headbuf.flip(); - super.finish(headbuf); - return; - } - if (context.getCharset() == null) { - if (interceptor != null) { - interceptor.invoke(this, new ByteBuffer[]{ByteBuffer.wrap(Utility.encodeUTF8(obj))}); - } - final char[] chars = Utility.charArray(obj); - this.contentLength = Utility.encodeUTF8Length(chars); - final ByteBuffer headbuf = createHeader(); - ByteBuffer buf2 = Utility.encodeUTF8(headbuf, (int) this.contentLength, chars); - headbuf.flip(); - if (buf2 == null) { - super.finish(headbuf); - } else { - super.finish(headbuf, buf2); - } - } else { - ByteBuffer buffer = context.getCharset().encode(obj); - if (interceptor != null) { - ByteBuffer[] bufs = interceptor.invoke(this, new ByteBuffer[]{buffer}); - if (bufs != null) buffer = bufs[0]; - } - this.contentLength = buffer.remaining(); - final ByteBuffer headbuf = createHeader(); - headbuf.flip(); - super.finish(headbuf, buffer); - } - } - - public void finish(int status, String message) { - this.status = status; - if (status != 200) super.refuseAlive(); - finish(message); - } - - public void finish304() { - super.finish(buffer304.duplicate()); - } - - public void finish404() { - super.finish(buffer404.duplicate()); - } - - @Override - public void finish(ByteBuffer buffer) { - finish(false, buffer); - } - - @Override - public void finish(boolean kill, ByteBuffer buffer) { - if (!this.headsended) { - this.contentLength = buffer == null ? 0 : buffer.remaining(); - ByteBuffer headbuf = createHeader(); - headbuf.flip(); - if (buffer == null) { - super.finish(kill, headbuf); - } else { - super.finish(kill, new ByteBuffer[]{headbuf, buffer}); - } - } else { - super.finish(kill, buffer); - } - } - - @Override - public void finish(ByteBuffer... buffers) { - finish(false, buffers); - } - - @Override - public void finish(boolean kill, ByteBuffer... buffers) { - if (interceptor != null) { - ByteBuffer[] bufs = interceptor.invoke(this, buffers); - if (bufs != null) buffers = bufs; - } - if (kill) refuseAlive(); - if (!this.headsended) { - long len = 0; - for (ByteBuffer buf : buffers) { - len += buf.remaining(); - } - this.contentLength = len; - ByteBuffer headbuf = createHeader(); - headbuf.flip(); - if (buffers == null) { - super.finish(kill, headbuf); - } else { - ByteBuffer[] newbuffers = new ByteBuffer[buffers.length + 1]; - newbuffers[0] = headbuf; - System.arraycopy(buffers, 0, newbuffers, 1, buffers.length); - super.finish(kill, newbuffers); - } - } else { - super.finish(kill, buffers); - } - } - - public void sendBody(ByteBuffer buffer, A attachment, CompletionHandler handler) { - if (!this.headsended) { - if (this.contentLength < 0) this.contentLength = buffer == null ? 0 : buffer.remaining(); - ByteBuffer headbuf = createHeader(); - headbuf.flip(); - if (buffer == null) { - super.send(headbuf, attachment, handler); - } else { - super.send(new ByteBuffer[]{headbuf, buffer}, attachment, handler); - } - } else { - super.send(buffer, attachment, handler); - } - } - - public void finish(File file) throws IOException { - finishFile(file, null); - } - - protected void finishFile(final File file, ByteBuffer fileBody) throws IOException { - if (file == null || !file.isFile() || !file.canRead()) { - finish404(); - return; - } - if (fileBody != null) fileBody = fileBody.duplicate().asReadOnlyBuffer(); - final long length = file.length(); - final String match = request.getHeader("If-None-Match"); - if (match != null && (file.lastModified() + "-" + length).equals(match)) { - finish304(); - return; - } - this.contentLength = fileBody == null ? file.length() : fileBody.remaining(); - this.contentType = MimeType.getByFilename(file.getName()); - if (this.contentType == null) this.contentType = "application/octet-stream"; - String range = request.getHeader("Range"); - if (range != null && (!range.startsWith("bytes=") || range.indexOf(',') >= 0)) range = null; - long start = -1; - long len = -1; - if (range != null) { - range = range.substring("bytes=".length()); - int pos = range.indexOf('-'); - start = pos == 0 ? 0 : Integer.parseInt(range.substring(0, pos)); - long end = (pos == range.length() - 1) ? -1 : Long.parseLong(range.substring(pos + 1)); - long clen = end > 0 ? (end - start + 1) : (file.length() - start); - this.status = 206; - addHeader("Accept-Ranges", "bytes"); - addHeader("Content-Range", "bytes " + start + "-" + (end > 0 ? end : length - 1) + "/" + length); - this.contentLength = clen; - len = end > 0 ? clen : end; - } - this.addHeader("ETag", file.lastModified() + "-" + length); - ByteBuffer hbuffer = createHeader(); - hbuffer.flip(); - if (fileBody == null) { - finishFile(hbuffer, file, start, len); - } else { - if (start >= 0) { - fileBody.position((int) start); - if (len > 0) fileBody.limit((int) (fileBody.position() + len)); - } - super.finish(hbuffer, fileBody); - } - } - - private void finishFile(ByteBuffer hbuffer, File file, long offset, long length) throws IOException { - this.channel.write(hbuffer, hbuffer, new TransferFileHandler(AsynchronousFileChannel.open(file.toPath(), options, ((HttpContext) context).getExecutor()), offset, length)); - } - - private ByteBuffer createHeader() { - this.headsended = true; - ByteBuffer buffer = this.context.pollBuffer(); - buffer.put(("HTTP/1.1 " + this.status + " " + (this.status == 200 ? "OK" : httpCodes.get(this.status)) + "\r\n").getBytes()); - - buffer.put(("Content-Type: " + (this.contentType == null ? "text/plain; charset=utf-8" : this.contentType) + "\r\n").getBytes()); - - if (this.contentLength > 0) { - buffer.put(("Content-Length: " + this.contentLength + "\r\n").getBytes()); - } - if (!this.request.isKeepAlive()) { - buffer.put("Connection: close\r\n".getBytes()); - } - if (this.defaultAddHeaders != null) { - for (String[] headers : this.defaultAddHeaders) { - if (headers.length > 2) { - String v = request.getHeader(headers[2]); - if (v != null) this.header.addValue(headers[0], v); - } else { - this.header.addValue(headers[0], headers[1]); - } - } - } - if (this.defaultSetHeaders != null) { - for (String[] headers : this.defaultSetHeaders) { - if (headers.length > 2) { - this.header.setValue(headers[0], request.getHeader(headers[2])); - } else { - this.header.setValue(headers[0], headers[1]); - } - } - } - for (Entry en : this.header.getStringEntrys()) { - buffer.put((en.name + ": " + en.getValue() + "\r\n").getBytes()); - } - if (request.newsessionid != null) { - String domain = defcookie == null ? null : defcookie.getDomain(); - if (domain == null) { - domain = ""; - } else { - domain = "Domain=" + domain + "; "; - } - String path = defcookie == null ? null : defcookie.getPath(); - if (path == null) path = "/"; - if (request.newsessionid.isEmpty()) { - buffer.put(("Set-Cookie: " + HttpRequest.SESSIONID_NAME + "=; " + domain + "Path=" + path + "; Max-Age=0; HttpOnly\r\n").getBytes()); - } else { - buffer.put(("Set-Cookie: " + HttpRequest.SESSIONID_NAME + "=" + request.newsessionid + "; " + domain + "Path=" + path + "; HttpOnly\r\n").getBytes()); - } - } - if (this.cookies != null) { - for (HttpCookie cookie : this.cookies) { - if (cookie == null) continue; - if (defcookie != null) { - if (defcookie.getDomain() != null && cookie.getDomain() == null) cookie.setDomain(defcookie.getDomain()); - if (defcookie.getPath() != null && cookie.getPath() == null) cookie.setPath(defcookie.getPath()); - } - buffer.put(("Set-Cookie: " + genString(cookie) + "\r\n").getBytes()); - } - } - buffer.put(LINE); - return buffer; - } - - private CharSequence genString(HttpCookie cookie) { - StringBuilder sb = new StringBuilder(); - sb.append(cookie.getName()).append("=\"").append(cookie.getValue()).append('"').append("; Version=1"); - if (cookie.getDomain() != null) sb.append("; Domain=").append(cookie.getDomain()); - if (cookie.getPath() != null) sb.append("; Path=").append(cookie.getPath()); - if (cookie.getPortlist() != null) sb.append("; Port=").append(cookie.getPortlist()); - if (cookie.getMaxAge() > 0) { - sb.append("; Max-Age=").append(cookie.getMaxAge()); - synchronized (GMT_DATE_FORMAT) { - sb.append("; Expires=").append(GMT_DATE_FORMAT.format(new Date(System.currentTimeMillis() + cookie.getMaxAge() * 1000))); - } - } - if (cookie.getSecure()) sb.append("; Secure"); - if (cookie.isHttpOnly()) sb.append("; HttpOnly"); - return sb; - } - - public void skipHeader() { - this.headsended = true; - } - - protected DefaultAnyValue duplicateHeader() { - return this.header.duplicate(); - } - - public void setHeader(String name, Object value) { - this.header.setValue(name, String.valueOf(value)); - } - - public void addHeader(String name, Object value) { - this.header.addValue(name, String.valueOf(value)); - } - - public void setStatus(int status) { - this.status = status; - } - - public int getStatus() { - return this.status; - } - - public String getContentType() { - return contentType; - } - - public void setContentType(String contentType) { - this.contentType = contentType; - } - - public long getContentLength() { - return contentLength; - } - - public void setContentLength(long contentLength) { - this.contentLength = contentLength; - } - - public Interceptor getInterceptor() { - return interceptor; - } - - public void setInterceptor(Interceptor interceptor) { - this.interceptor = interceptor; - } - - protected final class TransferFileHandler implements CompletionHandler { - - private final AsynchronousFileChannel filechannel; - - private final long max; //需要读取的字节数, -1表示读到文件结尾 - - private long count;//读取文件的字节数 - - private long position = 0; - - private boolean next = false; - - private boolean read = true; - - public TransferFileHandler(AsynchronousFileChannel channel) { - this.filechannel = channel; - this.max = -1; - } - - public TransferFileHandler(AsynchronousFileChannel channel, long offset, long len) { - this.filechannel = channel; - this.position = offset <= 0 ? 0 : offset; - this.max = len; - } - - @Override - public void completed(Integer result, ByteBuffer attachment) { - if (result < 0 || (max > 0 && count >= max)) { - failed(null, attachment); - return; - } - if (read) { - read = false; - if (next) { - position += result; - } else { - next = true; - } - attachment.clear(); - filechannel.read(attachment, position, attachment, this); - } else { - read = true; - if (max > 0) { - count += result; - if (count > max) { - attachment.limit((int) (attachment.position() + max - count)); - } - } - attachment.flip(); - channel.write(attachment, attachment, this); - } - } - - @Override - public void failed(Throwable exc, ByteBuffer attachment) { - getContext().offerBuffer(attachment); - finish(true); - try { - filechannel.close(); - } catch (IOException e) { - } - } - - } -} diff --git a/src/com/wentch/redkale/net/http/HttpServer.java b/src/com/wentch/redkale/net/http/HttpServer.java deleted file mode 100644 index 375671a6a..000000000 --- a/src/com/wentch/redkale/net/http/HttpServer.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.net.*; -import com.wentch.redkale.util.*; -import com.wentch.redkale.watch.*; -import java.net.*; -import java.nio.*; -import java.util.*; -import java.util.concurrent.atomic.*; - -/** - * - * @author zhangjx - */ -public final class HttpServer extends Server { - - private String contextPath; - - public HttpServer() { - this(System.currentTimeMillis(), null); - } - - public HttpServer(long serverStartTime, final WatchFactory watch) { - super(serverStartTime, "TCP", new HttpPrepareServlet(), watch); - } - - @Override - public void init(AnyValue config) throws Exception { - super.init(config); - AnyValue conf = config == null ? null : config.getAnyValue("servlets"); - this.contextPath = conf == null ? "" : conf.getValue("prefix", ""); - } - - public void addHttpServlet(HttpServlet servlet, AnyValue conf, String... mappings) { - ((HttpPrepareServlet) this.prepare).addHttpServlet(servlet, conf, mappings); - } - - @Override - @SuppressWarnings("unchecked") - protected Context createContext() { - final int port = this.address.getPort(); - AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("HTTP_" + port + ".Buffer.creatCounter"); - AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("HTTP_" + port + ".Buffer.cycleCounter"); - final int rcapacity = Math.max(this.capacity, 16 * 1024 + 8); //兼容 HTTP 2.0 - ObjectPool bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, this.bufferPoolSize, - (Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> { - if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false; - e.clear(); - return true; - }); - final List defaultAddHeaders = new ArrayList<>(); - final List defaultSetHeaders = new ArrayList<>(); - HttpCookie defaultCookie = null; - String remoteAddrHeader = null; - if (config != null) { - AnyValue reqs = config == null ? null : config.getAnyValue("request"); - if (reqs != null) { - AnyValue raddr = reqs.getAnyValue("remoteaddr"); - remoteAddrHeader = raddr == null ? null : raddr.getValue("value"); - if (remoteAddrHeader != null) { - if (remoteAddrHeader.startsWith("request.headers.")) { - remoteAddrHeader = remoteAddrHeader.substring("request.headers.".length()); - } else { - remoteAddrHeader = null; - } - } - } - - AnyValue resps = config == null ? null : config.getAnyValue("response"); - if (resps != null) { - AnyValue[] addHeaders = resps.getAnyValues("addheader"); - if (addHeaders.length > 0) { - for (int i = 0; i < addHeaders.length; i++) { - String val = addHeaders[i].getValue("value"); - if (val == null) continue; - if (val.startsWith("request.headers.")) { - defaultAddHeaders.add(new String[]{addHeaders[i].getValue("name"), val, val.substring("request.headers.".length())}); - } else if (val.startsWith("system.property.")) { - String v = System.getProperty(val.substring("system.property.".length())); - if (v != null) defaultAddHeaders.add(new String[]{addHeaders[i].getValue("name"), v}); - } else { - defaultAddHeaders.add(new String[]{addHeaders[i].getValue("name"), val}); - } - } - } - AnyValue[] setHeaders = resps.getAnyValues("setheader"); - if (setHeaders.length > 0) { - for (int i = 0; i < setHeaders.length; i++) { - String val = setHeaders[i].getValue("value"); - if (val != null && val.startsWith("request.headers.")) { - defaultSetHeaders.add(new String[]{setHeaders[i].getValue("name"), val, val.substring("request.headers.".length())}); - } else { - defaultSetHeaders.add(new String[]{setHeaders[i].getValue("name"), val}); - } - } - } - AnyValue defcookieValue = resps.getAnyValue("defcookie"); - if (defcookieValue != null) { - String domain = defcookieValue.getValue("domain"); - String path = defcookieValue.getValue("path"); - if (domain != null || path != null) { - defaultCookie = new HttpCookie("DEFAULTCOOKIE", ""); - defaultCookie.setDomain(domain); - defaultCookie.setPath(path); - } - } - } - } - final String[][] addHeaders = defaultAddHeaders.isEmpty() ? null : defaultAddHeaders.toArray(new String[defaultAddHeaders.size()][]); - final String[][] setHeaders = defaultSetHeaders.isEmpty() ? null : defaultSetHeaders.toArray(new String[defaultSetHeaders.size()][]); - final HttpCookie defCookie = defaultCookie; - final String addrHeader = remoteAddrHeader; - AtomicLong createResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("HTTP_" + port + ".Response.creatCounter"); - AtomicLong cycleResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("HTTP_" + port + ".Response.cycleCounter"); - ObjectPool responsePool = HttpResponse.createPool(createResponseCounter, cycleResponseCounter, this.responsePoolSize, null); - HttpContext httpcontext = new HttpContext(this.serverStartTime, this.logger, executor, rcapacity, bufferPool, responsePool, - this.maxbody, this.charset, this.address, this.prepare, this.watch, this.readTimeoutSecond, this.writeTimeoutSecond, contextPath); - responsePool.setCreator((Object... params) -> new HttpResponse(httpcontext, new HttpRequest(httpcontext, addrHeader), addHeaders, setHeaders, defCookie)); - return httpcontext; - } - -} diff --git a/src/com/wentch/redkale/net/http/HttpServlet.java b/src/com/wentch/redkale/net/http/HttpServlet.java deleted file mode 100644 index e50674572..000000000 --- a/src/com/wentch/redkale/net/http/HttpServlet.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.net.Servlet; -import com.wentch.redkale.util.*; - -/** - * - * @author zhangjx - */ -public abstract class HttpServlet implements Servlet> { - - AnyValue conf; //当前HttpServlet的配置 - - @Override - public final boolean equals(Object obj) { - return obj != null && obj.getClass() == this.getClass(); - } - - @Override - public final int hashCode() { - return this.getClass().hashCode(); - } - -} diff --git a/src/com/wentch/redkale/net/http/MimeType.java b/src/com/wentch/redkale/net/http/MimeType.java deleted file mode 100644 index 04e40d270..000000000 --- a/src/com/wentch/redkale/net/http/MimeType.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import java.util.*; - -/** - * - * @author zhangjx - */ -public class MimeType { - - private final static Map contentTypes = new HashMap<>(); - - static { - contentTypes.put("abs", "audio/x-mpeg"); - contentTypes.put("ai", "application/postscript"); - contentTypes.put("aif", "audio/x-aiff"); - contentTypes.put("aifc", "audio/x-aiff"); - contentTypes.put("aiff", "audio/x-aiff"); - contentTypes.put("aim", "application/x-aim"); - contentTypes.put("art", "image/x-jg"); - contentTypes.put("asf", "video/x-ms-asf"); - contentTypes.put("asx", "video/x-ms-asf"); - contentTypes.put("au", "audio/basic"); - contentTypes.put("avi", "video/x-msvideo"); - contentTypes.put("avx", "video/x-rad-screenplay"); - contentTypes.put("bcpio", "application/x-bcpio"); - contentTypes.put("bin", "application/octet-stream"); - contentTypes.put("bmp", "image/bmp"); - contentTypes.put("body", "text/html"); - contentTypes.put("cdf", "application/x-cdf"); - contentTypes.put("cer", "application/x-x509-ca-cert"); - contentTypes.put("class", "application/java"); - contentTypes.put("cpio", "application/x-cpio"); - contentTypes.put("csh", "application/x-csh"); - contentTypes.put("css", "text/css"); - contentTypes.put("dib", "image/bmp"); - contentTypes.put("doc", "application/msword"); - contentTypes.put("dtd", "application/xml-dtd"); - contentTypes.put("dv", "video/x-dv"); - contentTypes.put("dvi", "application/x-dvi"); - contentTypes.put("eps", "application/postscript"); - contentTypes.put("etx", "text/x-setext"); - contentTypes.put("exe", "application/octet-stream"); - contentTypes.put("gif", "image/gif"); - contentTypes.put("gk", "application/octet-stream"); - contentTypes.put("gtar", "application/x-gtar"); - contentTypes.put("gz", "application/x-gzip"); - contentTypes.put("hdf", "application/x-hdf"); - contentTypes.put("hqx", "application/mac-binhex40"); - contentTypes.put("htc", "text/x-component"); - contentTypes.put("htm", "text/html"); - contentTypes.put("html", "text/html"); - contentTypes.put("hqx", "application/mac-binhex40"); - contentTypes.put("ief", "image/ief"); - contentTypes.put("jad", "text/vnd.sun.j2me.app-descriptor"); - contentTypes.put("jar", "application/java-archive"); - contentTypes.put("java", "text/plain"); - contentTypes.put("jnlp", "application/x-java-jnlp-file"); - contentTypes.put("jpe", "image/jpeg"); - contentTypes.put("jpeg", "image/jpeg"); - contentTypes.put("jpg", "image/jpeg"); - contentTypes.put("js", "text/javascript"); - contentTypes.put("kar", "audio/x-midi"); - contentTypes.put("latex", "application/x-latex"); - contentTypes.put("log", "text/plain"); - contentTypes.put("m3u", "audio/x-mpegurl"); - contentTypes.put("mac", "image/x-macpaint"); - contentTypes.put("man", "application/x-troff-man"); - contentTypes.put("mathml", "application/mathml+xml"); - contentTypes.put("me", "application/x-troff-me"); - contentTypes.put("mid", "audio/x-midi"); - contentTypes.put("midi", "audio/x-midi"); - contentTypes.put("mif", "application/x-mif"); - contentTypes.put("mov", "video/quicktime"); - contentTypes.put("movie", "video/x-sgi-movie"); - contentTypes.put("mp1", "audio/x-mpeg"); - contentTypes.put("mp2", "audio/x-mpeg"); - contentTypes.put("mp3", "audio/x-mpeg"); - contentTypes.put("mpa", "audio/x-mpeg"); - contentTypes.put("mp4", "video/mp4"); - contentTypes.put("ogv", "video/ogv"); - contentTypes.put("webm", "video/webm"); - contentTypes.put("flv", "video/x-flv"); - contentTypes.put("mpe", "video/mpeg"); - contentTypes.put("mpeg", "video/mpeg"); - contentTypes.put("mpega", "audio/x-mpeg"); - contentTypes.put("mpg", "video/mpeg"); - contentTypes.put("mpv2", "video/mpeg2"); - contentTypes.put("ms", "application/x-wais-source"); - contentTypes.put("nc", "application/x-netcdf"); - contentTypes.put("oda", "application/oda"); - contentTypes.put("ogg", "application/ogg"); - contentTypes.put("out", "text/plain"); - contentTypes.put("pbm", "image/x-portable-bitmap"); - contentTypes.put("pct", "image/pict"); - contentTypes.put("pdf", "application/pdf"); - contentTypes.put("pgm", "image/x-portable-graymap"); - contentTypes.put("pic", "image/pict"); - contentTypes.put("pict", "image/pict"); - contentTypes.put("pls", "audio/x-scpls"); - contentTypes.put("png", "image/png"); - contentTypes.put("pnm", "image/x-portable-anymap"); - contentTypes.put("pnt", "image/x-macpaint"); - contentTypes.put("ppm", "image/x-portable-pixmap"); - contentTypes.put("ppt", "application/powerpoint"); - contentTypes.put("ps", "application/postscript"); - contentTypes.put("psd", "image/x-photoshop"); - contentTypes.put("qt", "video/quicktime"); - contentTypes.put("qti", "image/x-quicktime"); - contentTypes.put("qtif", "image/x-quicktime"); - contentTypes.put("ras", "image/x-cmu-raster"); - contentTypes.put("rdf", "application/rdf+xml"); - contentTypes.put("rgb", "image/x-rgb"); - contentTypes.put("rm", "application/vnd.rn-realmedia"); - contentTypes.put("roff", "application/x-troff"); - contentTypes.put("rtf", "application/rtf"); - contentTypes.put("rtx", "text/richtext"); - contentTypes.put("sh", "application/x-sh"); - contentTypes.put("shar", "application/x-shar"); - contentTypes.put("shtml", "text/x-server-parsed-html"); - contentTypes.put("sit", "application/x-stuffit"); - contentTypes.put("smf", "audio/x-midi"); - contentTypes.put("snd", "audio/basic"); - contentTypes.put("src", "application/x-wais-source"); - contentTypes.put("sv4cpio", "application/x-sv4cpio"); - contentTypes.put("sv4crc", "application/x-sv4crc"); - contentTypes.put("svg", "image/svg+xml"); - contentTypes.put("svgz", "image/svg+xml"); - contentTypes.put("swf", "application/x-shockwave-flash"); - contentTypes.put("t", "application/x-troff"); - contentTypes.put("tar", "application/x-tar"); - contentTypes.put("tcl", "application/x-tcl"); - contentTypes.put("tex", "application/x-tex"); - contentTypes.put("texi", "application/x-texinfo"); - contentTypes.put("texinfo", "application/x-texinfo"); - contentTypes.put("tif", "image/tiff"); - contentTypes.put("tiff", "image/tiff"); - contentTypes.put("tr", "application/x-troff"); - contentTypes.put("tsv", "text/tab-separated-values"); - contentTypes.put("txt", "text/plain"); - contentTypes.put("ulw", "audio/basic"); - contentTypes.put("ustar", "application/x-ustar"); - contentTypes.put("xbm", "image/x-xbitmap"); - contentTypes.put("xml", "application/xml"); - contentTypes.put("xpm", "image/x-xpixmap"); - contentTypes.put("xsl", "application/xml"); - contentTypes.put("xslt", "application/xslt+xml"); - contentTypes.put("xwd", "image/x-xwindowdump"); - contentTypes.put("vsd", "application/x-visio"); - contentTypes.put("vxml", "application/voicexml+xml"); - contentTypes.put("wav", "audio/x-wav"); - contentTypes.put("wbmp", "image/vnd.wap.wbmp"); - contentTypes.put("wml", "text/vnd.wap.wml"); - contentTypes.put("wmlc", "application/vnd.wap.wmlc"); - contentTypes.put("wmls", "text/vnd.wap.wmls"); - contentTypes.put("wmlscriptc", "application/vnd.wap.wmlscriptc"); - contentTypes.put("wrl", "x-world/x-vrml"); - contentTypes.put("xht", "application/xhtml+xml"); - contentTypes.put("xhtml", "application/xhtml+xml"); - contentTypes.put("xls", "application/vnd.ms-excel"); - contentTypes.put("xul", "application/vnd.mozilla.xul+xml"); - contentTypes.put("Z", "application/x-compress"); - contentTypes.put("z", "application/x-compress"); - contentTypes.put("zip", "application/zip"); - } - - /** - * @param extension the extension - * - * @return the content type associated with extension. If no association is found, this method will return text/plain - */ - public static String get(String extension) { - return get(extension, "text/plain"); - } - - /** - * @param extension the extension - * @param defaultCt the content type to return if there is no known association for the specified extension - * - * @return the content type associated with extension or if no associate is found, returns defaultCt - */ - public static String get(String extension, String defaultCt) { - final String mime = contentTypes.get(extension); - return mime == null ? defaultCt : mime; - } - - /** - * @param extension the extension - * - * @return true if the specified extension has been registered otherwise, returns false - */ - public static boolean contains(String extension) { - return contentTypes.containsKey(extension); - } - - /** - *

- * Associates the specified extension and content type

- * - * @param extension the extension - * @param contentType the content type associated with the extension - */ - public static void add(String extension, String contentType) { - if (extension != null && extension.length() != 0 - && contentType != null && contentType.length() != 0) { - contentTypes.put(extension, contentType); - } - } - - /** - * @param fileName the filename - * - * @return the content type associated with extension of the given filename or if no associate is found, returns null - */ - public static String getByFilename(String fileName) { - String extn = getExtension(fileName); - return extn == null ? null : get(extn); - } - - /** - * Get extension of file, without fragment id - */ - private static String getExtension(String fileName) { - // play it safe and get rid of any fragment id - // that might be there - int length = fileName.length(); - - int newEnd = fileName.lastIndexOf('#'); - if (newEnd == -1) newEnd = length; - // Instead of creating a new string. - // if (i != -1) fileName = fileName.substring(0, i); - int i = fileName.lastIndexOf('.', newEnd); - return i == -1 ? null : fileName.substring(i + 1, newEnd); - } -} diff --git a/src/com/wentch/redkale/net/http/MultiContext.java b/src/com/wentch/redkale/net/http/MultiContext.java deleted file mode 100644 index cef906b7b..000000000 --- a/src/com/wentch/redkale/net/http/MultiContext.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * To change this license header, choose License Headers input Project Properties. - * To change this template file, choose Tools | Templates - * and open the template input the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.util.ByteArray; -import java.io.*; -import java.nio.charset.*; -import java.util.*; -import java.util.concurrent.atomic.*; -import java.util.logging.*; -import java.util.regex.*; - -/** - * - * @author zhangjx - */ -public final class MultiContext { - - private static final Logger logger = Logger.getLogger(MultiContext.class.getSimpleName()); - - private static final Charset UTF8 = Charset.forName("UTF-8"); - - private final String contentType; - - private final InputStream in; - - private final Charset charset; - - private final String boundary; - - private final byte[] endboundarray; - - private final ByteArray buf = new ByteArray(64); - - private final Map parameters = new HashMap<>(); - - private final Pattern fielnamePattern; - - private static final Iterable emptyIterable = () -> new Iterator() { - - @Override - public boolean hasNext() { - return false; - } - - @Override - public MultiPart next() { - return null; - } - }; - - public MultiContext(final String contentType, final InputStream in) { - this(null, contentType, in); - } - - public MultiContext(final Charset charsetName, final String contentType, final InputStream in) { - this(charsetName, contentType, in, null); - } - - public MultiContext(final String contentType, final InputStream in, String extregex) { - this(null, contentType, in, extregex); - } - - public MultiContext(final Charset charsetName, final String contentType, final InputStream in, String fielnameRegex) { - this.charset = charsetName == null ? UTF8 : charsetName; - this.contentType = contentType.trim(); - this.boundary = parseBoundary(this.contentType); - this.endboundarray = ("--" + this.boundary + "--").getBytes(); - this.in = in instanceof BufferedInputStream ? in : new BufferedInputStream(in); - this.fielnamePattern = fielnameRegex == null || fielnameRegex.isEmpty() ? null : Pattern.compile(fielnameRegex); - } - - public Map getParameters() { - return parameters; - } - - public String getParameter(String name) { - return getParameters().get(name); - } - - public final String getParameter(String name, String defaultValue) { - String value = this.getParameter(name); - return value == null ? defaultValue : value; - } - - public final int getIntParameter(String name, int defaultValue) { - String value = this.getParameter(name); - try { - return value == null ? defaultValue : Integer.decode(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - public final long getLongParameter(String name, long defaultValue) { - String value = this.getParameter(name); - try { - return value == null ? defaultValue : Long.decode(value); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - private String parseBoundary(String contentType) { - if (!contentType.startsWith("multipart/")) { - return null; - } - for (String str : contentType.split(";")) { - int pos = str.indexOf("boundary="); - if (pos >= 0) return str.substring(pos + "boundary=".length()).trim(); - } - return null; - } - - public boolean isMultipart() { - return this.boundary != null; - } - - public Iterable listMultiPart() throws IOException { - if (!isMultipart()) return emptyIterable; - final boolean debug = true; - final String boundarystr = "--" + this.boundary; - final Pattern fielnameReg = this.fielnamePattern; - final String endboundary = boundarystr + "--"; - final byte[] boundarray = ("\n" + boundarystr).getBytes(); - final byte[] buffer = new byte[boundarray.length]; - final InputStream input = this.in; - final Map params = this.parameters; - final AtomicBoolean finaled = new AtomicBoolean(false); - return () -> new Iterator() { - - private String boundaryline; - - private MultiPart lastentry; - - @Override - public boolean hasNext() { - try { - if (lastentry != null) { - lastentry.skip(); - if (finaled.get()) return false; - } - if (boundaryline == null) boundaryline = readBoundary(); - //if (debug) System.out.print("boundaryline=" + boundaryline + " "); - if (endboundary.equals(boundaryline) || !boundarystr.equals(boundaryline)) { //结尾或异常 - lastentry = null; - return false; - } - final String disposition = readLine(); - //if (debug) System.out.println("disposition=" + disposition); - if (disposition.contains("; filename=\"")) { //是上传文件 - String contentType = readLine(); - //if (debug) System.out.println("file.contentType=" + contentType); - contentType = contentType.substring(contentType.indexOf(':') + 1).trim(); - readLine(); //读掉空白行 - String name = parseValue(disposition, "name"); - String filename = parseValue(disposition, "filename"); - if (filename == null || filename.isEmpty()) { //没有上传 - readLine(); //读掉空白行 - this.boundaryline = null; - this.lastentry = null; - return this.hasNext(); - } else { - int p1 = filename.lastIndexOf('/'); - if (p1 < 0) p1 = filename.lastIndexOf('\\'); - if (p1 >= 0) filename = filename.substring(p1 + 1); - } - final AtomicLong counter = new AtomicLong(0); - InputStream source = new InputStream() { - - private int bufposition = buffer.length; - - private boolean end; - - @Override - public int read() throws IOException { - if (end) return -1; - final byte[] buf = buffer; - int ch = (this.bufposition < buf.length) ? (buf[this.bufposition++] & 0xff) : input.read(); - if ((ch == '\r' && readBuffer())) return -1; - counter.incrementAndGet(); - return ch; - } - - private boolean readBuffer() throws IOException { - final byte[] buf = buffer; - final int pos = this.bufposition; - int s = 0; - for (int i = pos; i < buf.length; i++) { - buf[s++] = buf[i]; - } - int readed = 0; - while ((readed += input.read(buf, s + readed, pos - readed)) != pos); - this.bufposition = 0; - if (Arrays.equals(boundarray, buf)) { - this.end = true; - int c1 = input.read(); - int c2 = input.read(); - finaled.set(c1 == '-' && c2 == '-'); - return true; - } - return false; - } - - @Override - public long skip(long count) throws IOException { - if (end) return -1; - if (count <= 0) return 0; - long s = 0; - while (read() != -1) { - s++; - if (--count <= 0) break; - } - return s; - } - }; - this.lastentry = new MultiPart(filename, name, contentType, counter, source); - if (fielnameReg != null && !fielnameReg.matcher(filename).matches()) { - return this.hasNext(); - } - return true; - } else { //不是文件 - readLine(); //读掉空白 - params.put(parseValue(disposition, "name"), readLine()); - this.boundaryline = null; - this.lastentry = null; - return this.hasNext(); - } - } catch (IOException ex) { - logger.log(Level.FINER, "listMultiPart abort", ex); - return false; - } - } - - @Override - public MultiPart next() { - return lastentry; - } - - }; - } - - private String readLine() throws IOException { - return readLine(false); - } - - private String readBoundary() throws IOException { - return readLine(true); - } - - private String readLine(boolean bd) throws IOException { // bd : 是否是读取boundary - byte lasted = '\r'; - buf.clear(); - final int bc = this.endboundarray.length; - int c = 0; - for (;;) { - int b = in.read(); - c++; - if (b == -1 || (lasted == '\r' && b == '\n')) break; - if (lasted != '\r') buf.add(lasted); - lasted = (byte) b; - if (bd && bc == c) { - buf.add(lasted); - if (buf.equal(this.endboundarray)) break; - buf.removeLastByte(); - } - } - if (buf.count() == 0) return ""; - return buf.toString(this.charset).trim(); - } - - private static String parseValue(final String str, String name) { - if (str == null) return null; - final String key = "; " + name + "=\""; - int pos = str.indexOf(key); - if (pos < 0) return null; - String sub = str.substring(pos + key.length()); - return sub.substring(0, sub.indexOf('"')); - } - -} diff --git a/src/com/wentch/redkale/net/http/MultiPart.java b/src/com/wentch/redkale/net/http/MultiPart.java deleted file mode 100644 index fd2f40c03..000000000 --- a/src/com/wentch/redkale/net/http/MultiPart.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import java.io.*; -import java.util.concurrent.atomic.AtomicLong; - -/** - * - * @author zhangjx - */ -public final class MultiPart { - - private final String filename; - - private final String name; - - private final String contentType; - - private final InputStream in; - - private final AtomicLong received; - - MultiPart(String filename, String name, String contentType, AtomicLong received, InputStream in) { - this.filename = filename; - this.name = name; - this.in = in; - this.contentType = contentType; - this.received = received; - } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "{" + "name=" + name + ", filename=" + filename + ", contentType=" + contentType + ", received=" + received + '}'; - } - - public boolean save(File file) throws IOException { - return save(Long.MAX_VALUE, file); - } - - public boolean save(long max, File file) throws IOException { - OutputStream out = new FileOutputStream(file); - boolean rs = save(max, out); - out.close(); - return rs; - } - - public byte[] getContentBytes() throws IOException { - return getContentBytes(Long.MAX_VALUE); - } - - /** - * 将文件流读进bytes, 如果超出max指定的值则返回null - * - * @param max 最大长度限制 - * @return - * @throws IOException - */ - public byte[] getContentBytes(long max) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - return save(max, out) ? out.toByteArray() : null; - } - - public boolean save(OutputStream out) throws IOException { - return save(Long.MAX_VALUE, out); - } - - /** - * 将文件流写进out, 如果超出max指定的值则中断并返回false - * - * @param max 最大长度限制 - * @param out - * @return - * @throws IOException - */ - public boolean save(long max, OutputStream out) throws IOException { - byte[] bytes = new byte[4096]; - int pos; - InputStream in0 = this.getInputStream(); - while ((pos = in0.read(bytes)) != -1) { - if (max < 0) return false; - out.write(bytes, 0, pos); - max -= pos; - } - return true; - } - - public String getContentType() { - return contentType; - } - - public String getFilename() { - return filename; - } - - public String getName() { - return name; - } - - public InputStream getInputStream() { - return in; - } - - public long getReceived() { - return received.get(); - } - - public void skip() throws IOException { - in.skip(Long.MAX_VALUE); - } - -} diff --git a/src/com/wentch/redkale/net/http/WebAction.java b/src/com/wentch/redkale/net/http/WebAction.java deleted file mode 100644 index f497c973a..000000000 --- a/src/com/wentch/redkale/net/http/WebAction.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import java.lang.annotation.*; - -/** - * - * @author zhangjx - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface WebAction { - - int actionid() default 0; - - String url(); -} diff --git a/src/com/wentch/redkale/net/http/WebInitParam.java b/src/com/wentch/redkale/net/http/WebInitParam.java deleted file mode 100644 index cfece07f4..000000000 --- a/src/com/wentch/redkale/net/http/WebInitParam.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import java.lang.annotation.*; - -/** - * - * @author zhangjx - */ -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface WebInitParam { - - String name(); - - String value(); - - String description() default ""; -} diff --git a/src/com/wentch/redkale/net/http/WebServlet.java b/src/com/wentch/redkale/net/http/WebServlet.java deleted file mode 100644 index cf2f6d3a9..000000000 --- a/src/com/wentch/redkale/net/http/WebServlet.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import java.lang.annotation.*; - -/** - * - * @author zhangjx - */ -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface WebServlet { - - String name() default ""; - - boolean fillurl() default true; - - String[] value() default {}; - - int moduleid() default 0; - - WebInitParam[] initParams() default {}; -} diff --git a/src/com/wentch/redkale/net/http/WebSocket.java b/src/com/wentch/redkale/net/http/WebSocket.java deleted file mode 100644 index 2e2b34421..000000000 --- a/src/com/wentch/redkale/net/http/WebSocket.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.net.*; -import com.wentch.redkale.net.http.WebSocketPacket.FrameType; -import java.io.*; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 一个WebSocket连接对应一个WebSocket实体,即一个WebSocket会绑定一个TCP连接。 - * WebSocket 有两种模式: - * 1) 普通模式: 协议上符合HTML5规范, 其流程顺序如下: - * 1.1 onOpen 如果方法返回null,则视为WebSocket的连接不合法,框架会强制关闭WebSocket连接;通常用于判断登录态。 - * 1.2 createGroupid 如果方法返回null,则视为WebSocket的连接不合法,框架会强制关闭WebSocket连接;通常用于判断用户权限是否符合。 - * 1.3 onConnected WebSocket成功连接后在准备接收数据前回调此方法。 - * 1.4 onMessage/onFragment+ WebSocket接收到消息后回调此消息类方法。 - * 1.5 onClose WebSocket被关闭后回调此方法。 - * - * 此模式下 以上方法都应该被重载。 - * - * 2) 原始二进制模式: 此模式有别于HTML5规范,可以视为原始的TCP连接。通常用于音频视频通讯场景。期流程顺序如下: - * 2.1 onOpen 如果方法返回null,则视为WebSocket的连接不合法,框架会强制关闭WebSocket连接;通常用于判断登录态。 - * 2.2 createGroupid 如果方法返回null,则视为WebSocket的连接不合法,框架会强制关闭WebSocket连接;通常用于判断用户权限是否符合。 - * 2.3 onRead WebSocket成功连接后回调此方法, 由此方法处理原始的TCP连接, 同时业务代码去控制WebSocket的关闭。 - * - * 此模式下 以上方法都应该被重载。 - *

- * - * @author zhangjx - */ -public abstract class WebSocket { - - //消息不合法 - public static final int RETCODE_SEND_ILLPACKET = 1 << 1; //2 - - //ws已经关闭 - public static final int RETCODE_WSOCKET_CLOSED = 1 << 2; //4 - - //socket的buffer不合法 - public static final int RETCODE_ILLEGALBUFFER = 1 << 3; //8 - - //ws发送消息异常 - public static final int RETCODE_SENDEXCEPTION = 1 << 4; //16 - - public static final int RETCODE_ENGINE_NULL = 1 << 5; //32 - - public static final int RETCODE_NODESERVICE_NULL = 1 << 6; //64 - - public static final int RETCODE_GROUP_EMPTY = 1 << 7; //128 - - public static final int RETCODE_WSOFFLINE = 1 << 8; //256 - - WebSocketRunner runner; - - WebSocketEngine engine; - - WebSocketGroup group; - - WebSocketNode node; - - Serializable sessionid; - - Serializable groupid; - - private final long createtime = System.currentTimeMillis(); - - private final Map attributes = new ConcurrentHashMap<>(); - - protected WebSocket() { - } - - //---------------------------------------------------------------- - /** - * 发送消息体, 包含二进制/文本 - *

- * @param packet - * @return - */ - public final int send(WebSocketPacket packet) { - if (this.runner != null) return this.runner.sendMessage(packet); - return RETCODE_WSOCKET_CLOSED; - } - - /** - * 显式地关闭WebSocket - */ - public final void close() { - if (this.runner != null) this.runner.closeRunner(); - } - - /** - * 发送单一的文本消息 - *

- * @param text 不可为空 - * @return - */ - public final int send(String text) { - return send(text, true); - } - - /** - * 发送文本消息 - *

- * @param text 不可为空 - * @param last 是否最后一条 - * @return - */ - public final int send(String text, boolean last) { - return send(new WebSocketPacket(text, last)); - } - - /** - * 发送单一的二进制消息 - *

- * @param data - * @return - */ - public final int send(byte[] data) { - return send(data, true); - } - - public final int sendPing(byte[] data) { - return send(new WebSocketPacket(FrameType.PING, data)); - } - - public final int sendPong(byte[] data) { - return send(new WebSocketPacket(FrameType.PONG, data)); - } - - public final long getCreatetime() { - return createtime; - } - - /** - * 发送二进制消息 - *

- * @param data 不可为空 - * @param last 是否最后一条 - * @return - */ - public final int send(byte[] data, boolean last) { - return send(new WebSocketPacket(data, last)); - } - - /** - * 发送消息, 消息类型是String或byte[] - *

- * @param message 不可为空, 只能是String或者byte[] - * @param last 是否最后一条 - * @return - */ - public final int send(Serializable message, boolean last) { - return send(new WebSocketPacket(message, last)); - } - - //---------------------------------------------------------------- - /** - * 给指定groupid的WebSocketGroup下所有WebSocket节点发送文本消息 - *

- * @param groupid - * @param text 不可为空 - * @return 为0表示成功, 其他值表示异常 - */ - public final int sendEachMessage(Serializable groupid, String text) { - return sendEachMessage(groupid, text, true); - } - - /** - * 给指定groupid的WebSocketGroup下所有WebSocket节点发送二进制消息 - *

- * @param groupid - * @param data 不可为空 - * @return 为0表示成功, 其他值表示异常 - */ - public final int sendEachMessage(Serializable groupid, byte[] data) { - return WebSocket.this.sendEachMessage(groupid, data, true); - } - - /** - * 给指定groupid的WebSocketGroup下所有WebSocket节点发送文本消息 - *

- * @param groupid - * @param text 不可为空 - * @param last - * @return 为0表示成功, 其他值表示异常 - */ - public final int sendEachMessage(Serializable groupid, String text, boolean last) { - return sendMessage(groupid, false, text, last); - } - - /** - * 给指定groupid的WebSocketGroup下所有WebSocket节点发送二进制消息 - *

- * @param groupid - * @param data 不可为空 - * @param last 是否最后一条 - * @return 为0表示成功, 其他值表示异常 - */ - public final int sendEachMessage(Serializable groupid, byte[] data, boolean last) { - return sendMessage(groupid, false, data, last); - } - - /** - * 给指定groupid的WebSocketGroup下最近活跃的WebSocket节点发送文本消息 - *

- * @param groupid - * @param text 不可为空 - * @return 为0表示成功, 其他值表示异常 - */ - public final int sendRecentMessage(Serializable groupid, String text) { - return sendRecentMessage(groupid, text, true); - } - - /** - * 给指定groupid的WebSocketGroup下最近活跃的WebSocket节点发送二进制消息 - *

- * @param groupid - * @param data 不可为空 - * @return 为0表示成功, 其他值表示异常 - */ - public final int sendRecentMessage(Serializable groupid, byte[] data) { - return sendRecentMessage(groupid, data, true); - } - - /** - * 给指定groupid的WebSocketGroup下最近活跃的WebSocket节点发送文本消息 - *

- * @param groupid - * @param text 不可为空 - * @param last 是否最后一条 - * @return 为0表示成功, 其他值表示异常 - */ - public final int sendRecentMessage(Serializable groupid, String text, boolean last) { - return sendMessage(groupid, true, text, last); - } - - /** - * 给指定groupid的WebSocketGroup下最近活跃的WebSocket节点发送二进制消息 - *

- * @param groupid - * @param data 不可为空 - * @param last 是否最后一条 - * @return 为0表示成功, 其他值表示异常 - */ - public final int sendRecentMessage(Serializable groupid, byte[] data, boolean last) { - return sendMessage(groupid, true, data, last); - } - - private int sendMessage(Serializable groupid, boolean recent, String text, boolean last) { - if (node == null) return RETCODE_NODESERVICE_NULL; - return node.sendMessage(groupid, recent, text, last); - } - - private int sendMessage(Serializable groupid, boolean recent, byte[] data, boolean last) { - if (node == null) return RETCODE_NODESERVICE_NULL; - return node.sendMessage(groupid, recent, data, last); - } - - /** - * 获取当前WebSocket下的属性 - *

- * @param - * @param name - * @return - */ - @SuppressWarnings("unchecked") - public final T getAttribute(String name) { - return (T) attributes.get(name); - } - - /** - * 移出当前WebSocket下的属性 - *

- * @param - * @param name - * @return - */ - public final T removeAttribute(String name) { - return (T) attributes.remove(name); - } - - /** - * 给当前WebSocket下的增加属性 - *

- * @param name - * @param value - */ - public final void setAttribute(String name, Object value) { - attributes.put(name, value); - } - - /** - * 获取当前WebSocket所属的groupid - *

- * @return - */ - public final Serializable getGroupid() { - return groupid; - } - - /** - * 获取当前WebSocket的会话ID, 不会为null - *

- * @return - */ - public final Serializable getSessionid() { - return sessionid; - } - - //------------------------------------------------------------------- - /** - * 获取当前WebSocket所属的WebSocketGroup, 不会为null - *

- * @return - */ - protected final WebSocketGroup getWebSocketGroup() { - return group; - } - - /** - * 获取指定groupid的WebSocketGroup, 没有返回null - *

- * @param groupid - * @return - */ - protected final WebSocketGroup getWebSocketGroup(Serializable groupid) { - return engine.getWebSocketGroup(groupid); - } - - protected final Collection getWebSocketGroups() { - return engine.getWebSocketGroups(); - } - - //------------------------------------------------------------------- - /** - * 返回sessionid, null表示连接不合法或异常 - * - * @param request - * @return - */ - public Serializable onOpen(final HttpRequest request) { - return request.getSessionid(false); - } - - /** - * 创建groupid, null表示异常 - * - * @return - */ - protected abstract Serializable createGroupid(); - - /** - * - * @param channel - */ - public void onRead(AsyncConnection channel) { - } - - public void onConnected() { - } - - public void onMessage(String text) { - } - - public void onPing(byte[] bytes) { - } - - public void onPong(byte[] bytes) { - } - - public void onMessage(byte[] bytes) { - } - - public void onFragment(String text, boolean last) { - } - - public void onFragment(byte[] bytes, boolean last) { - } - - public void onClose(int code, String reason) { - } -} diff --git a/src/com/wentch/redkale/net/http/WebSocketBinary.java b/src/com/wentch/redkale/net/http/WebSocketBinary.java deleted file mode 100644 index 042d78995..000000000 --- a/src/com/wentch/redkale/net/http/WebSocketBinary.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * 被标记为 @WebSocketBinary 的WebSocketServlet 将使用原始的TCP传输, 通常用于类似音频/视频传输场景 - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({TYPE}) -@Retention(RUNTIME) -public @interface WebSocketBinary { - -} diff --git a/src/com/wentch/redkale/net/http/WebSocketEngine.java b/src/com/wentch/redkale/net/http/WebSocketEngine.java deleted file mode 100644 index acac0aeb7..000000000 --- a/src/com/wentch/redkale/net/http/WebSocketEngine.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import static com.wentch.redkale.net.http.WebSocketPacket.DEFAULT_PING_PACKET; -import static com.wentch.redkale.net.http.WebSocketServlet.DEFAILT_LIVEINTERVAL; -import com.wentch.redkale.util.*; -import java.io.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import java.util.logging.*; - -/** - * - * @author zhangjx - */ -public final class WebSocketEngine { - - private static final AtomicInteger sequence = new AtomicInteger(); - - private final int index; - - private final String engineid; - - private final Map containers = new ConcurrentHashMap<>(); - - private ScheduledThreadPoolExecutor scheduler; - - protected final Logger logger; - - protected final boolean finest; - - protected WebSocketEngine(String engineid, Logger logger) { - this.engineid = engineid; - this.logger = logger; - this.index = sequence.getAndIncrement(); - this.finest = logger.isLoggable(Level.FINEST); - } - - void init(AnyValue conf) { - final int liveinterval = conf == null ? DEFAILT_LIVEINTERVAL : conf.getIntValue("liveinterval", DEFAILT_LIVEINTERVAL); - if (liveinterval == 0) return; - if (scheduler != null) return; - this.scheduler = new ScheduledThreadPoolExecutor(1, (Runnable r) -> { - final Thread t = new Thread(r, engineid + "-WebSocket-LiveInterval-Thread"); - t.setDaemon(true); - return t; - }); - long delay = (liveinterval - System.currentTimeMillis() / 1000 % liveinterval) + index * 5; - scheduler.scheduleWithFixedDelay(() -> { - getWebSocketGroups().stream().forEach(x -> x.sendEach(DEFAULT_PING_PACKET)); - //if (finest) logger.finest(engineid + " ping..."); - }, delay, liveinterval, TimeUnit.SECONDS); - if (finest) logger.finest(this.getClass().getSimpleName() + "(" + engineid + ")" + " start keeplive(delay:" + delay + ", interval:" + liveinterval + "s) scheduler executor"); - } - - void add(WebSocket socket) { - WebSocketGroup group = containers.get(socket.groupid); - if (group == null) { - group = new WebSocketGroup(socket.groupid); - containers.put(socket.groupid, group); - } - group.add(socket); - } - - void remove(WebSocket socket) { - WebSocketGroup group = containers.get(socket.groupid); - if (group == null) return; - group.remove(socket); - if (group.isEmpty()) containers.remove(socket.groupid); - } - - Collection getWebSocketGroups() { - return containers.values(); - } - - public WebSocketGroup getWebSocketGroup(Serializable groupid) { - return containers.get(groupid); - } - - void close() { - if (scheduler != null) scheduler.shutdownNow(); - } - - public String getEngineid() { - return engineid; - } -} diff --git a/src/com/wentch/redkale/net/http/WebSocketGroup.java b/src/com/wentch/redkale/net/http/WebSocketGroup.java deleted file mode 100644 index b79648c6d..000000000 --- a/src/com/wentch/redkale/net/http/WebSocketGroup.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import java.io.*; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.stream.Stream; - -/** - * - * @author zhangjx - */ -public final class WebSocketGroup { - - private final Serializable groupid; - - private WebSocket recentWebSocket; - - private final List list = new CopyOnWriteArrayList<>(); - - private final Map attributes = new HashMap<>(); - - WebSocketGroup(Serializable groupid) { - this.groupid = groupid; - } - - public Serializable getGroupid() { - return groupid; - } - - public Stream getWebSockets() { - return list.stream(); - } - - void remove(WebSocket socket) { - list.remove(socket); - } - - void add(WebSocket socket) { - socket.group = this; - this.recentWebSocket = socket; - list.add(socket); - } - - void setRecentWebSocket(WebSocket socket) { - this.recentWebSocket = socket; - } - - public final boolean isEmpty() { - return list.isEmpty(); - } - - public final int size() { - return list.size(); - } - - /** - * 最近发送消息的WebSocket - *

- * @return - */ - public final WebSocket getRecentWebSocket() { - return recentWebSocket; - } - - @SuppressWarnings("unchecked") - public final T getAttribute(String name) { - return (T) attributes.get(name); - } - - public final void removeAttribute(String name) { - attributes.remove(name); - } - - public final void setAttribute(String name, Object value) { - attributes.put(name, value); - } - - public final int send(boolean recent, Serializable message, boolean last) { - if (recent) { - return recentWebSocket.send(message, last); - } else { - return sendEach(message, last); - } - } - - public final int sendEach(Serializable message) { - return sendEach(message, true); - } - - public final int sendEach(WebSocketPacket packet) { - int rs = 0; - for (WebSocket s : list) { - rs |= s.send(packet); - } - return rs; - } - - public final int sendRecent(Serializable message) { - return sendRecent(message, true); - } - - public final int sendRecent(WebSocketPacket packet) { - return recentWebSocket.send(packet); - } - - public final int sendEach(Serializable message, boolean last) { - int rs = 0; - for (WebSocket s : list) { - rs |= s.send(message, last); - } - return rs; - } - - public final int sendRecent(Serializable message, boolean last) { - return recentWebSocket.send(message, last); - } - - @Override - public String toString() { - return "{groupid: " + groupid + ", list.size: " + (list == null ? -1 : list.size()) + "}"; - } - -} diff --git a/src/com/wentch/redkale/net/http/WebSocketNode.java b/src/com/wentch/redkale/net/http/WebSocketNode.java deleted file mode 100644 index 527f3bdfb..000000000 --- a/src/com/wentch/redkale/net/http/WebSocketNode.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import static com.wentch.redkale.net.http.WebSocket.*; -import com.wentch.redkale.net.sncp.*; -import com.wentch.redkale.util.*; -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.logging.*; -import javax.annotation.*; - -/** - * - * @author zhangjx - */ -public abstract class WebSocketNode { - - protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName()); - - protected final boolean finest = logger.isLoggable(Level.FINEST); - - @Resource(name = "SERVER_ADDR") - protected InetSocketAddress localSncpAddress; //为SncpServer的服务address - - @SncpRemote - protected WebSocketNode remoteNode; - - //存放所有用户分布在节点上的队列信息,Set 为 sncpnode 的集合 - protected final ConcurrentHashMap> dataNodes = new ConcurrentHashMap(); - - //存放所有用户分布在节点上的队列信息,Set 为 engineid 的集合 - protected final ConcurrentHashMap> localNodes = new ConcurrentHashMap(); - - protected final ConcurrentHashMap engines = new ConcurrentHashMap(); - - public void init(AnyValue conf) { - if (remoteNode != null) { - new Thread() { - { - setDaemon(true); - } - - @Override - public void run() { - try { - Map> map = remoteNode.getDataNodes(); - if (map != null) dataNodes.putAll(map); - } catch (Exception e) { - logger.log(Level.INFO, WebSocketNode.class.getSimpleName() + "(" + localSncpAddress + ") not load data nodes ", e); - } - } - }.start(); - } - } - - public void destroy(AnyValue conf) { - HashMap> nodes = new HashMap<>(localNodes); - nodes.forEach((k, v) -> { - new HashSet<>(v).forEach(e -> { - if (engines.containsKey(e)) disconnect(k, e); - }); - }); - } - - public Map> getDataNodes() { - return dataNodes; - } - - protected abstract int sendMessage(@SncpTargetAddress InetSocketAddress addr, Serializable groupid, boolean recent, Serializable message, boolean last); - - protected abstract void connect(Serializable groupid, InetSocketAddress addr); - - protected abstract void disconnect(Serializable groupid, InetSocketAddress addr); - - //-------------------------------------------------------------------------------- - public final void connect(Serializable groupid, String engineid) { - if (finest) logger.finest(localSncpAddress + " receive websocket connect event (" + groupid + " on " + engineid + ")."); - Set engineids = localNodes.get(groupid); - if (engineids == null) { - engineids = new CopyOnWriteArraySet<>(); - localNodes.put(groupid, engineids); - } - if (localSncpAddress != null && engineids.isEmpty()) connect(groupid, localSncpAddress); - engineids.add(engineid); - } - - public final void disconnect(Serializable groupid, String engineid) { - if (finest) logger.finest(localSncpAddress + " receive websocket disconnect event (" + groupid + " on " + engineid + ")."); - Set engineids = localNodes.get(groupid); - if (engineids == null || engineids.isEmpty()) return; - engineids.remove(engineid); - if (engineids.isEmpty()) { - localNodes.remove(groupid); - if (localSncpAddress != null) disconnect(groupid, localSncpAddress); - } - } - - public final void putWebSocketEngine(WebSocketEngine engine) { - engines.put(engine.getEngineid(), engine); - } - - public final int sendMessage(Serializable groupid, boolean recent, Serializable message, boolean last) { - final Set engineids = localNodes.get(groupid); - int rscode = RETCODE_GROUP_EMPTY; - if (engineids != null && !engineids.isEmpty()) { - for (String engineid : engineids) { - final WebSocketEngine engine = engines.get(engineid); - if (engine != null) { //在本地 - final WebSocketGroup group = engine.getWebSocketGroup(groupid); - if (group == null || group.isEmpty()) { - if (finest) logger.finest("receive websocket but result is " + RETCODE_GROUP_EMPTY + " in message {engineid:'" + engineid + "', groupid:" + groupid + ", content:'" + message + "'}"); - rscode = RETCODE_GROUP_EMPTY; - break; - } - rscode = group.send(recent, message, last); - } - } - } - if ((recent && rscode == 0) || remoteNode == null) return rscode; - LinkedHashSet addrs = dataNodes.get(groupid); - if (addrs != null && !addrs.isEmpty()) { //对方连接在远程节点 - if (recent) { - InetSocketAddress one = null; - for (InetSocketAddress addr : addrs) { - one = addr; - } - rscode = remoteNode.sendMessage(one, groupid, recent, message, last); - } else { - for (InetSocketAddress addr : addrs) { - if (!addr.equals(localSncpAddress)) { - rscode |= remoteNode.sendMessage(addr, groupid, recent, message, last); - } - } - } - } else { - rscode = RETCODE_GROUP_EMPTY; - } - return rscode; - } - - //-------------------------------------------------------------------------------- - public final int sendEachMessage(Serializable groupid, String text) { - return sendMessage(groupid, false, text); - } - - public final int sendEachMessage(Serializable groupid, String text, boolean last) { - return sendMessage(groupid, false, text, last); - } - - public final int sendRecentMessage(Serializable groupid, String text) { - return sendMessage(groupid, true, text); - } - - public final int sendRecentMessage(Serializable groupid, String text, boolean last) { - return sendMessage(groupid, true, text, last); - } - - public final int sendMessage(Serializable groupid, boolean recent, String text) { - return sendMessage(groupid, recent, text, true); - } - - public final int sendMessage(Serializable groupid, boolean recent, String text, boolean last) { - return sendMessage(groupid, recent, (Serializable) text, last); - } - - //-------------------------------------------------------------------------------- - public final int sendEachMessage(Serializable groupid, byte[] data) { - return sendMessage(groupid, false, data); - } - - public final int sendEachMessage(Serializable groupid, byte[] data, boolean last) { - return sendMessage(groupid, false, data, last); - } - - public final int sendRecentMessage(Serializable groupid, byte[] data) { - return sendMessage(groupid, true, data); - } - - public final int sendRecentMessage(Serializable groupid, byte[] data, boolean last) { - return sendMessage(groupid, true, data, last); - } - - public final int sendMessage(Serializable groupid, boolean recent, byte[] data) { - return sendMessage(groupid, recent, data, true); - } - - public final int sendMessage(Serializable groupid, boolean recent, byte[] data, boolean last) { - return sendMessage(groupid, recent, (Serializable) data, last); - } -} diff --git a/src/com/wentch/redkale/net/http/WebSocketPacket.java b/src/com/wentch/redkale/net/http/WebSocketPacket.java deleted file mode 100644 index 947e83ae6..000000000 --- a/src/com/wentch/redkale/net/http/WebSocketPacket.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.util.Utility; -import java.io.*; -import java.util.*; - -/** - * - * @author zhangjx - */ -public final class WebSocketPacket { - - public static final WebSocketPacket DEFAULT_PING_PACKET = new WebSocketPacket(FrameType.PING, new byte[0]); - - public static enum FrameType { - - TEXT(0x01), BINARY(0x02), CLOSE(0x08), PING(0x09), PONG(0x0A); - - private final int value; - - private FrameType(int v) { - this.value = v; - } - - public int getValue() { - return value; - } - - public static FrameType valueOf(int v) { - switch (v) { - case 0x01: return TEXT; - case 0x02: return BINARY; - case 0x08: return CLOSE; - case 0x09: return PING; - case 0x0A: return PONG; - default: return null; - } - } - } - - protected FrameType type; - - protected String payload; - - protected byte[] bytes; - - protected boolean last = true; - - public WebSocketPacket() { - } - - public WebSocketPacket(String payload) { - this(payload, true); - } - - public WebSocketPacket(Serializable message, boolean fin) { - boolean bin = message != null && message.getClass() == byte[].class; - if (bin) { - this.type = FrameType.BINARY; - this.bytes = (byte[]) message; - } else { - this.type = FrameType.TEXT; - this.payload = String.valueOf(message); - } - this.last = fin; - } - - public WebSocketPacket(String payload, boolean fin) { - this.type = FrameType.TEXT; - this.payload = payload; - this.last = fin; - } - - public WebSocketPacket(byte[] data) { - this(FrameType.BINARY, data, true); - } - - public WebSocketPacket(byte[] data, boolean fin) { - this(FrameType.BINARY, data, fin); - } - - public WebSocketPacket(FrameType type, byte[] data) { - this(type, data, true); - } - - public WebSocketPacket(FrameType type, byte[] data, boolean fin) { - this.type = type; - if (type == FrameType.TEXT) { - this.payload = new String(Utility.decodeUTF8(data)); - } else { - this.bytes = data; - } - this.last = fin; - } - - public byte[] getContent() { - if (this.type == FrameType.TEXT) return Utility.encodeUTF8(getPayload()); - if (this.bytes == null) return new byte[0]; - return this.bytes; - } - - public String getPayload() { - return payload; - } - - public byte[] getBytes() { - return bytes; - } - - public boolean isLast() { - return last; - } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "[type=" + type + ", last=" + last + (payload != null ? (", payload=" + payload) : "") + (bytes != null ? (", bytes=" + Arrays.toString(bytes)) : "") + "]"; - } -} diff --git a/src/com/wentch/redkale/net/http/WebSocketRunner.java b/src/com/wentch/redkale/net/http/WebSocketRunner.java deleted file mode 100644 index 6e8ce7d8d..000000000 --- a/src/com/wentch/redkale/net/http/WebSocketRunner.java +++ /dev/null @@ -1,529 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.net.AsyncConnection; -import com.wentch.redkale.net.Context; -import static com.wentch.redkale.net.http.WebSocket.*; -import com.wentch.redkale.net.http.WebSocketPacket.FrameType; -import java.nio.ByteBuffer; -import java.nio.channels.*; -import java.security.SecureRandom; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.logging.*; - -/** - * - * @author zhangjx - */ -public class WebSocketRunner implements Runnable { - - private final WebSocketEngine engine; - - private final AsyncConnection channel; - - private final WebSocket webSocket; - - protected final Context context; - - private ByteBuffer readBuffer; - - private ByteBuffer writeBuffer; - - protected boolean closed = false; - - private AtomicBoolean writing = new AtomicBoolean(); - - private final Coder coder = new Coder(); - - private final BlockingQueue queue = new ArrayBlockingQueue(1024); - - private final boolean wsbinary; - - public WebSocketRunner(Context context, WebSocket webSocket, AsyncConnection channel, final boolean wsbinary) { - this.context = context; - this.engine = webSocket.engine; - this.webSocket = webSocket; - this.channel = channel; - this.wsbinary = wsbinary; - webSocket.runner = this; - this.coder.logger = context.getLogger(); - this.coder.debugable = false;//context.getLogger().isLoggable(Level.FINEST); - this.readBuffer = context.pollBuffer(); - this.writeBuffer = context.pollBuffer(); - } - - @Override - public void run() { - final boolean debug = this.coder.debugable; - try { - if (webSocket.node != null) webSocket.node.connect(webSocket.groupid, webSocket.engine.getEngineid()); - webSocket.onConnected(); - channel.setReadTimeoutSecond(300); //读取超时5分钟 - if (channel.isOpen()) { - if (wsbinary) { - webSocket.onRead(channel); - return; - } - channel.read(readBuffer, null, new CompletionHandler() { - - private ByteBuffer recentExBuffer; - - //当接收的数据流长度大于ByteBuffer长度时, 则需要额外的ByteBuffer 辅助; - private final List readBuffers = new ArrayList<>(); - - @Override - public void completed(Integer count, Void attachment1) { - if (count < 1 && readBuffers.isEmpty()) { - closeRunner(); - if (debug) context.getLogger().log(Level.FINEST, "WebSocketRunner abort on read buffer count, force to close channel, live " + (System.currentTimeMillis() - webSocket.getCreatetime()) / 1000 + " seconds"); - return; - } - if (readBuffer == null) return; - if (!readBuffer.hasRemaining() && (recentExBuffer == null || !recentExBuffer.hasRemaining())) { - final ByteBuffer buffer = context.pollBuffer(); - recentExBuffer = buffer; - readBuffers.add(buffer); - channel.read(buffer, null, this); - return; - } - readBuffer.flip(); - try { - ByteBuffer[] exBuffers = null; - if (!readBuffers.isEmpty()) { - exBuffers = readBuffers.toArray(new ByteBuffer[readBuffers.size()]); - readBuffers.clear(); - recentExBuffer = null; - for (ByteBuffer b : exBuffers) { - b.flip(); - } - } - WebSocketPacket packet = coder.decode(readBuffer, exBuffers); - if (exBuffers != null) { - for (ByteBuffer b : exBuffers) { - context.offerBuffer(b); - } - } - if (packet == null) { - failed(null, attachment1); - if (debug) context.getLogger().log(Level.FINEST, "WebSocketRunner abort on decode WebSocketPacket, force to close channel, live " + (System.currentTimeMillis() - webSocket.getCreatetime()) / 1000 + " seconds"); - return; - } - if (readBuffer != null) { - readBuffer.clear(); - channel.read(readBuffer, null, this); - } - webSocket.group.setRecentWebSocket(webSocket); - try { - if (packet.type == FrameType.TEXT) { - webSocket.onMessage(packet.getPayload()); - } else if (packet.type == FrameType.BINARY) { - webSocket.onMessage(packet.getBytes()); - } else if (packet.type == FrameType.PONG) { - webSocket.onPong(packet.getBytes()); - } else if (packet.type == FrameType.PING) { - webSocket.onPing(packet.getBytes()); - } - } catch (Exception e) { - context.getLogger().log(Level.INFO, "WebSocket onMessage error (" + packet + ")", e); - } - } catch (Throwable t) { - closeRunner(); - if (debug) context.getLogger().log(Level.FINEST, "WebSocketRunner abort on read WebSocketPacket, force to close channel, live " + (System.currentTimeMillis() - webSocket.getCreatetime()) / 1000 + " seconds", t); - } - } - - @Override - public void failed(Throwable exc, Void attachment2) { - closeRunner(); - if (exc != null) { - context.getLogger().log(Level.FINEST, "WebSocketRunner read WebSocketPacket failed, force to close channel, live " + (System.currentTimeMillis() - webSocket.getCreatetime()) / 1000 + " seconds", exc); - } - } - }); - } else { - closeRunner(); - context.getLogger().log(Level.FINEST, "WebSocketRunner abort by AsyncConnection closed"); - } - } catch (Exception e) { - closeRunner(); - context.getLogger().log(Level.FINEST, "WebSocketRunner abort on read bytes from channel, force to close channel, live " + (System.currentTimeMillis() - webSocket.getCreatetime()) / 1000 + " seconds", e); - } - } - - public int sendMessage(WebSocketPacket packet) { - if (packet == null) return RETCODE_SEND_ILLPACKET; - if (closed) return RETCODE_WSOCKET_CLOSED; - final boolean debug = this.coder.debugable; - //System.out.println("推送消息"); - final byte[] bytes = coder.encode(packet); - if (debug) context.getLogger().log(Level.FINEST, "send web socket message's length = " + bytes.length); - if (writing.getAndSet(true)) { - queue.add(bytes); - return 0; - } - if (writeBuffer == null) return RETCODE_ILLEGALBUFFER; - ByteBuffer sendBuffer = null; - if (bytes.length <= writeBuffer.capacity()) { - writeBuffer.clear(); - writeBuffer.put(bytes); - writeBuffer.flip(); - sendBuffer = writeBuffer; - } else { - sendBuffer = ByteBuffer.wrap(bytes); - } - try { - channel.write(sendBuffer, sendBuffer, new CompletionHandler() { - - @Override - public void completed(Integer result, ByteBuffer attachment) { - if (attachment == null || closed) return; - try { - if (attachment.hasRemaining()) { - if (debug) context.getLogger().log(Level.FINEST, "WebSocketRunner write completed reemaining: " + attachment.remaining()); - channel.write(attachment, attachment, this); - return; - } - byte[] bs = queue.poll(); - if (bs != null && writeBuffer != null) { - ByteBuffer sendBuffer; - if (bs.length <= writeBuffer.capacity()) { - writeBuffer.clear(); - writeBuffer.put(bs); - writeBuffer.flip(); - sendBuffer = writeBuffer; - } else { - sendBuffer = ByteBuffer.wrap(bs); - } - channel.write(sendBuffer, sendBuffer, this); - return; - } - } catch (NullPointerException e) { - } catch (Exception e) { - closeRunner(); - context.getLogger().log(Level.WARNING, "WebSocket sendMessage abort on rewrite, force to close channel, live " + (System.currentTimeMillis() - webSocket.getCreatetime()) / 1000 + " seconds", e); - } - writing.set(false); - } - - @Override - public void failed(Throwable exc, ByteBuffer attachment) { - writing.set(false); - closeRunner(); - if (exc != null) { - context.getLogger().log(Level.FINE, "WebSocket sendMessage on CompletionHandler failed, force to close channel, live " + (System.currentTimeMillis() - webSocket.getCreatetime()) / 1000 + " seconds", exc); - } - } - }); - return 0; - } catch (Exception t) { - writing.set(false); - closeRunner(); - context.getLogger().log(Level.FINE, "WebSocket sendMessage abort, force to close channel, live " + (System.currentTimeMillis() - webSocket.getCreatetime()) / 1000 + " seconds", t); - return RETCODE_SENDEXCEPTION; - } - } - - public void closeRunner() { - if (closed) return; - synchronized (this) { - if (closed) return; - closed = true; - try { - channel.close(); - } catch (Throwable t) { - } - context.offerBuffer(readBuffer); - context.offerBuffer(writeBuffer); - readBuffer = null; - writeBuffer = null; - engine.remove(webSocket); - if (webSocket.node != null) { - WebSocketGroup group = webSocket.getWebSocketGroup(); - if (group == null || group.isEmpty()) webSocket.node.disconnect(webSocket.groupid, webSocket.engine.getEngineid()); - } - webSocket.onClose(0, null); - } - } - - private static final class Masker { - - public static final int MASK_SIZE = 4; - - private ByteBuffer buffer; - - private ByteBuffer[] exbuffers; - - private byte[] mask; - - private int index = 0; - - public Masker(ByteBuffer buffer, ByteBuffer... exbuffers) { - this.buffer = buffer; - this.exbuffers = exbuffers == null || exbuffers.length == 0 ? null : exbuffers; - } - - public Masker() { - generateMask(); - } - - public int remaining() { - int r = buffer.remaining(); - if (exbuffers != null) { - for (ByteBuffer b : exbuffers) { - r += b.remaining(); - } - } - return r; - } - - public byte get() { - return buffer.get(); - } - - public byte[] get(final int size) { - byte[] bytes = new byte[size]; - if (buffer.remaining() >= size) { - buffer.get(bytes); - } else { //必须有 exbuffers - int offset = buffer.remaining(); - buffer.get(bytes, 0, buffer.remaining()); - for (ByteBuffer b : exbuffers) { - b.get(bytes, offset, b.remaining()); - offset += b.remaining(); - } - } - return bytes; - } - - public byte unmask() { - final byte b = get(); - return mask == null ? b : (byte) (b ^ mask[index++ % MASK_SIZE]); - } - - public byte[] unmask(int count) { - byte[] bytes = get(count); - if (mask != null) { - for (int i = 0; i < bytes.length; i++) { - bytes[i] ^= mask[index++ % MASK_SIZE]; - } - } - - return bytes; - } - - public void generateMask() { - mask = new byte[MASK_SIZE]; - new SecureRandom().nextBytes(mask); - } - - public void mask(byte[] bytes, int location, byte b) { - bytes[location] = mask == null ? b : (byte) (b ^ mask[index++ % MASK_SIZE]); - } - - public void mask(byte[] target, int location, byte[] bytes) { - if (bytes != null && target != null) { - for (int i = 0; i < bytes.length; i++) { - target[location + i] = mask == null ? bytes[i] : (byte) (bytes[i] ^ mask[index++ % MASK_SIZE]); - } - } - } - - public byte[] maskAndPrepend(byte[] packet) { - byte[] masked = new byte[packet.length + MASK_SIZE]; - System.arraycopy(getMask(), 0, masked, 0, MASK_SIZE); - mask(masked, MASK_SIZE, packet); - return masked; - } - - public void setBuffer(ByteBuffer buffer) { - this.buffer = buffer; - } - - public byte[] getMask() { - return mask; - } - - public void readMask() { - mask = get(MASK_SIZE); - } - } - - private static final class Coder { - - protected byte inFragmentedType; - - protected byte outFragmentedType; - - protected final boolean maskData = false; - - protected boolean processingFragment; - - private boolean debugable; - - private Logger logger; - - /** - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-------+-+-------------+-------------------------------+ - |F|R|R|R| opcode|M| Payload len | Extended payload length | - |I|S|S|S| (4) |A| (7) | (16/64) | - |N|V|V|V| |S| | (if payload len==126/127) | - | |1|2|3| |K| | | - +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + - | Extended payload length continued, if payload len == 127 | - + - - - - - - - - - - - - - - - +-------------------------------+ - | |Masking-key, if MASK set to 1 | - +-------------------------------+-------------------------------+ - | Masking-key (continued) | Payload Data | - +-------------------------------- - - - - - - - - - - - - - - - + - : Payload Data continued : - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - | Payload Data continued | - +-----------------------------------------------------------------------+ - @param buffer - @param exbuffers - @return - */ - public WebSocketPacket decode(final ByteBuffer buffer, ByteBuffer... exbuffers) { - final boolean debug = this.debugable; - if (debug) { - int remain = buffer.remaining(); - if (exbuffers != null) { - for (ByteBuffer b : exbuffers) { - remain += b == null ? 0 : b.remaining(); - } - } - logger.log(Level.FINEST, "read web socket message's length = " + remain); - } - if (buffer.remaining() < 2) return null; - byte opcode = buffer.get(); - final boolean last = (opcode & 0b1000000) != 0; - final boolean checkrsv = false;//暂时不校验 - if (checkrsv && (opcode & 0b01110000) != 0) { - if (debug) logger.log(Level.FINE, "rsv1 rsv2 rsv3 must be 0, but not (" + opcode + ")"); - return null; //rsv1 rsv2 rsv3 must be 0 - } - //0x00 表示一个后续帧 - //0x01 表示一个文本帧 - //0x02 表示一个二进制帧 - //0x03-07 为以后的非控制帧保留 - //0x8 表示一个连接关闭 - //0x9 表示一个ping - //0xA 表示一个pong - //0x0B-0F 为以后的控制帧保留 - final boolean control = (opcode & 0x08) == 0x08; //是否控制帧 - //final boolean continuation = opcode == 0; - FrameType type = FrameType.valueOf(opcode & 0xf); - if (type == FrameType.CLOSE) { - if (debug) logger.log(Level.FINEST, " receive close command from websocket client"); - return null; - } - byte lengthCode = buffer.get(); - final Masker masker = new Masker(buffer, exbuffers); - final boolean masked = (lengthCode & 0x80) == 0x80; - if (masked) lengthCode ^= 0x80; //mask - int length; - if (lengthCode <= 125) { - length = lengthCode; - } else { - if (control) { - if (debug) logger.log(Level.FINE, " receive control command from websocket client"); - return null; - } - - final int lengthBytes = lengthCode == 126 ? 2 : 8; - if (buffer.remaining() < lengthBytes) { - if (debug) logger.log(Level.FINE, " read illegal message length from websocket, expect " + lengthBytes + " but " + buffer.remaining()); - return null; - } - length = toInt(masker.unmask(lengthBytes)); - } - if (masked) { - if (buffer.remaining() < Masker.MASK_SIZE) { - if (debug) logger.log(Level.FINE, " read illegal masker length from websocket, expect " + Masker.MASK_SIZE + " but " + buffer.remaining()); - return null; - } - masker.readMask(); - } - if (masker.remaining() < length) { - if (debug) logger.log(Level.FINE, " read illegal remaining length from websocket, expect " + length + " but " + masker.remaining()); - return null; - } - final byte[] data = masker.unmask(length); - if (data.length != length) { - if (debug) logger.log(Level.FINE, " read illegal unmask length from websocket, expect " + length + " but " + data.length); - return null; - } - return new WebSocketPacket(type, data, last); - } - - public byte[] encode(WebSocketPacket frame) { - byte opcode = (byte) (frame.type.getValue() | 0x80); - final byte[] bytes = frame.getContent(); - final byte[] lengthBytes = encodeLength(bytes.length); - - int length = 1 + lengthBytes.length + bytes.length + (maskData ? Masker.MASK_SIZE : 0); - int payloadStart = 1 + lengthBytes.length + (maskData ? Masker.MASK_SIZE : 0); - final byte[] packet = new byte[length]; - packet[0] = opcode; - System.arraycopy(lengthBytes, 0, packet, 1, lengthBytes.length); - if (maskData) { - Masker masker = new Masker(); - packet[1] |= 0x80; - masker.mask(packet, payloadStart, bytes); - System.arraycopy(masker.getMask(), 0, packet, payloadStart - Masker.MASK_SIZE, Masker.MASK_SIZE); - } else { - System.arraycopy(bytes, 0, packet, payloadStart, bytes.length); - } - return packet; - } - - private static byte[] encodeLength(final int length) { - byte[] lengthBytes; - if (length <= 125) { - lengthBytes = new byte[1]; - lengthBytes[0] = (byte) length; - } else { - byte[] b = toArray(length); - if (length <= 0xFFFF) { - lengthBytes = new byte[3]; - lengthBytes[0] = 126; - System.arraycopy(b, 6, lengthBytes, 1, 2); - } else { - lengthBytes = new byte[9]; - lengthBytes[0] = 127; - System.arraycopy(b, 0, lengthBytes, 1, 8); - } - } - return lengthBytes; - } - - private static byte[] toArray(long length) { - long value = length; - byte[] b = new byte[8]; - for (int i = 7; i >= 0 && value > 0; i--) { - b[i] = (byte) (value & 0xFF); - value >>= 8; - } - return b; - } - - private static int toInt(byte[] bytes) { - int value = 0; - for (int i = 0; i < bytes.length; i++) { - value <<= 8; - value ^= (int) bytes[i] & 0xFF; - } - return value; - } - - } - -} diff --git a/src/com/wentch/redkale/net/http/WebSocketServlet.java b/src/com/wentch/redkale/net/http/WebSocketServlet.java deleted file mode 100644 index d6eaa2699..000000000 --- a/src/com/wentch/redkale/net/http/WebSocketServlet.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.http; - -import com.wentch.redkale.net.*; -import com.wentch.redkale.util.*; -import java.io.*; -import java.net.*; -import java.nio.*; -import java.nio.channels.*; -import java.security.*; -import java.util.*; -import java.util.logging.*; -import javax.annotation.*; - -/** - * 当WebSocketServlet接收一个TCP连接后,进行协议判断,如果成功就会创建一个WebSocket。 - * - * WebSocketServlet - * | - * | - * WebSocketEngine - * / \ - * / \ - * / \ - * WebSocketGroup1 WebSocketGroup2 - * / \ / \ - * / \ / \ - * WebSocket1 WebSocket2 WebSocket3 WebSocket4 - * - * @author zhangjx - */ -public abstract class WebSocketServlet extends HttpServlet implements Nameable { - - public static final String WEBPARAM__LIVEINTERVAL = "liveinterval"; - - public static final int DEFAILT_LIVEINTERVAL = 60; - - protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName()); - - private final MessageDigest digest = getMessageDigest(); - - private static MessageDigest getMessageDigest() { - try { - return MessageDigest.getInstance("SHA-1"); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - //是否用于二进制流传输 - protected final boolean wsbinary = getClass().getAnnotation(WebSocketBinary.class) != null; - - @Resource(name = "$") - protected WebSocketNode node; - - protected WebSocketEngine engine; - - @Override - public void init(Context context, AnyValue conf) { - InetSocketAddress addr = context.getServerAddress(); - this.engine = new WebSocketEngine(addr.getHostString() + ":" + addr.getPort() + "-" + name(), logger); - this.node.putWebSocketEngine(engine); - this.node.init(conf); - this.engine.init(conf); - } - - @Override - public void destroy(Context context, AnyValue conf) { - this.node.destroy(conf); - super.destroy(context, conf); - engine.close(); - } - - @Override - public String name() { - return this.getClass().getSimpleName().replace("Servlet", "").replace("WebSocket", "").toLowerCase(); - } - - @Override - public final void execute(final HttpRequest request, final HttpResponse response) throws IOException { - final boolean debug = logger.isLoggable(Level.FINEST); - if (!"GET".equalsIgnoreCase(request.getMethod()) - || !request.getConnection().contains("Upgrade") - || !"websocket".equalsIgnoreCase(request.getHeader("Upgrade"))) { - if (debug) logger.finest("WebSocket connect abort, (Not GET Method) or (Connection != Upgrade) or (Upgrade != websocket). request=" + request); - response.finish(true); - return; - } - String key = request.getHeader("Sec-WebSocket-Key"); - if (key == null) { - if (debug) logger.finest("WebSocket connect abort, Not found Sec-WebSocket-Key header. request=" + request); - response.finish(true); - return; - } - final WebSocket webSocket = this.createWebSocket(); - webSocket.engine = engine; - webSocket.node = node; - Serializable sessionid = webSocket.onOpen(request); - if (sessionid == null) { - if (debug) logger.finest("WebSocket connect abort, Not found sessionid. request=" + request); - response.finish(true); - return; - } - webSocket.sessionid = sessionid; - request.setKeepAlive(true); - byte[] bytes = (key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes(); - synchronized (digest) { - bytes = digest.digest(bytes); - } - key = Base64.getEncoder().encodeToString(bytes); - response.setStatus(101); - response.setHeader("Connection", "Upgrade"); - response.addHeader("Upgrade", "websocket"); - response.addHeader("Sec-WebSocket-Accept", key); - response.sendBody((ByteBuffer) null, null, new CompletionHandler() { - - @Override - public void completed(Integer result, Void attachment) { - HttpContext context = response.getContext(); - Serializable groupid = webSocket.createGroupid(); - if (groupid == null) { - if (debug) logger.finest("WebSocket connect abort, Create groupid abort. request = " + request); - response.finish(true); - return; - } - webSocket.groupid = groupid; - engine.add(webSocket); - context.submit(new WebSocketRunner(context, webSocket, response.removeChannel(), wsbinary)); - response.finish(true); - } - - @Override - public void failed(Throwable exc, Void attachment) { - logger.log(Level.FINEST, "WebSocket connect abort, Response send abort. request = " + request, exc); - response.finish(true); - } - }); - } - - protected abstract WebSocket createWebSocket(); -} diff --git a/src/com/wentch/redkale/net/sncp/ServiceWrapper.java b/src/com/wentch/redkale/net/sncp/ServiceWrapper.java deleted file mode 100644 index 8f9a129b5..000000000 --- a/src/com/wentch/redkale/net/sncp/ServiceWrapper.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import com.wentch.redkale.boot.*; -import com.wentch.redkale.service.Service; -import com.wentch.redkale.util.AnyValue; -import java.util.*; - -/** - * Service对象的封装类 - * - * @author zhangjx - * @param - */ -public final class ServiceWrapper { - - private final Class type; - - private final T service; - - private final AnyValue conf; - - private final String group; - - private final Set groups; - - private final String name; - - private final boolean remote; - - public ServiceWrapper(Class type, T service, String group, ClassFilter.FilterEntry entry) { - this(type, service, entry.getName(), group, entry.getGroups(), entry.getProperty()); - } - - public ServiceWrapper(Class type, T service, String name, String group, Set groups, AnyValue conf) { - this.type = type == null ? (Class) service.getClass() : type; - this.service = service; - this.conf = conf; - this.group = group; - this.groups = groups; - this.name = name; - this.remote = Sncp.isRemote(service); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null) return false; - if (!(obj instanceof ServiceWrapper)) return false; - ServiceWrapper other = (ServiceWrapper) obj; - return (this.type.equals(other.type) && this.remote == other.remote && this.name.equals(other.name) && this.group.equals(other.group)); - } - - @Override - public int hashCode() { - int hash = 3; - hash = 67 * hash + Objects.hashCode(this.type); - hash = 67 * hash + Objects.hashCode(this.group); - hash = 67 * hash + Objects.hashCode(this.name); - hash = 67 * hash + (this.remote ? 1 : 0); - return hash; - } - - public Class getType() { - return type; - } - - public Service getService() { - return service; - } - - public AnyValue getConf() { - return conf; - } - - public String getName() { - return service.name(); - } - - public boolean isRemote() { - return remote; - } - - public Set getGroups() { - return groups; - } - -} diff --git a/src/com/wentch/redkale/net/sncp/Sncp.java b/src/com/wentch/redkale/net/sncp/Sncp.java deleted file mode 100644 index 180a53034..000000000 --- a/src/com/wentch/redkale/net/sncp/Sncp.java +++ /dev/null @@ -1,1108 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import com.wentch.redkale.convert.bson.*; -import com.wentch.redkale.net.*; -import com.wentch.redkale.net.sncp.SncpClient.SncpAction; -import com.wentch.redkale.service.*; -import com.wentch.redkale.util.*; -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.net.*; -import java.util.*; -import java.util.function.*; -import javax.annotation.*; -import jdk.internal.org.objectweb.asm.*; -import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES; -import static jdk.internal.org.objectweb.asm.Opcodes.*; -import jdk.internal.org.objectweb.asm.Type; - -/** - * 生成Service的本地模式或远程模式Service-Class的工具类 - * - * @author zhangjx - */ -public abstract class Sncp { - - //当前SNCP Server的IP地址+端口 类型: SocketAddress、InetSocketAddress、String - public static final String RESNAME_SNCP_ADDR = "SNCP_ADDR"; - - //当前Service所属的组 类型: Set、String[] - public static final String RESNAME_SNCP_GROUPS = "SNCP_GROUPS"; - - private static final java.lang.reflect.Type GROUPS_TYPE1 = new TypeToken>() { - }.getType(); - - private static final java.lang.reflect.Type GROUPS_TYPE2 = new TypeToken() { - }.getType(); - - static final String LOCALPREFIX = "_DynLocal"; - - static final String REMOTEPREFIX = "_DynRemote"; - - private static final byte[] hashes = new byte[255]; - - static { - //0-9:48-57 A-Z:65-90 a-z:97-122 $:36 _:95 - byte index = 0; - hashes['_'] = index++; - hashes['$'] = index++; - for (int i = '0'; i <= '9'; i++) { - hashes[i] = index++; - } - for (int i = 'A'; i <= 'Z'; i++) { - hashes[i] = index++; - } - for (int i = 'a'; i <= 'z'; i++) { - hashes[i] = index++; - } - } - - private Sncp() { - } - - public static long nodeid(InetSocketAddress ip) { - byte[] bytes = ip.getAddress().getAddress(); - return ((0L + ip.getPort()) << 32) | ((0xffffffff & bytes[0]) << 24) | ((0xffffff & bytes[1]) << 16) | ((0xffff & bytes[2]) << 8) | (0xff & bytes[3]); - } - - public static long hash(final Class clazz) { - if (clazz == null) return Long.MIN_VALUE; - long rs = hash(clazz.getSimpleName()); - return (rs < Integer.MAX_VALUE) ? rs | 0xF00000000L : rs; - } - - public static long hashClass(final String clazzName) { - if (clazzName == null || clazzName.isEmpty()) return Long.MIN_VALUE; - long rs = hash(clazzName.substring(clazzName.lastIndexOf('.') + 1)); - return (rs < Integer.MAX_VALUE) ? rs | 0xF00000000L : rs; - } - - public static DLong hash(final java.lang.reflect.Method method) { - if (method == null) return new DLong(-1L, -1L); - String n = method.getName(); - if (n.length() > 11) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < n.length(); i += 2) { - sb.append(n.charAt(i)); - } - sb.append(n.length()); - n = sb.toString(); - } - long rs1 = hash(n); - if (rs1 < Integer.MAX_VALUE) rs1 |= (method.getParameterCount() + 0L) << 32; - rs1 = (rs1 < Integer.MAX_VALUE) ? rs1 | 0xF00000000L : rs1; - - long rs2 = hash(wrapName(method), true); - if (rs2 < Integer.MAX_VALUE) rs2 |= (method.getParameterCount() + 0L) << 32; - rs2 = (rs2 < Integer.MAX_VALUE) ? rs2 | 0xF00000000L : rs2; - return new DLong(rs1, rs2); - } - - private static String wrapName(final java.lang.reflect.Method method) { - final Class[] params = method.getParameterTypes(); - if (params.length == 0) return method.getName() + "00"; - StringBuilder sb = new StringBuilder(); - for (Class clzz : params) { - String s = clzz.getSimpleName(); - sb.append(s.substring(0, s.length() > 1 ? 2 : 1)).append(s.substring(s.length() - 1)); - } - String n = method.getName(); - if (n.length() > 11) { - StringBuilder zsb = new StringBuilder(); - for (int i = 0; i < n.length(); i += 2) { - zsb.append(n.charAt(i)); - } - zsb.append(n.length()); - n = zsb.toString(); - } - return n + sb + Integer.toString(params.length, 36); - } - - public static long hash(final String name) { - return hash(name, false); - } - - public static long hash(final String name, boolean reverse) { - if (name == null) return Long.MIN_VALUE; - if (name.isEmpty()) return 0; - char[] chars = Utility.charArray(name); - long rs = 0L; - if (reverse) { - int start = Math.max(chars.length - 10, 0); - for (int i = chars.length - 1; i >= start; i--) { - rs = (rs << 6) | hashes[0xff & chars[i]]; - } - } else { - int end = Math.min(chars.length, 11); - for (int i = 0; i < end; i++) { - rs = (rs << 6) | hashes[0xff & chars[i]]; - } - } - return Math.abs(rs); - } - - public static boolean isRemote(Service service) { - return service.getClass().getName().startsWith(REMOTEPREFIX); - } - - /** - * public class TestService implements Service{ - * - * public String queryNode(){ - * return "hello"; - * } - * - * @MultiRun - * public String updateSomeThing(String id){ - * return "hello" + id; - * } - * - * @MultiRun(selfrun = false) - * public void createSomeThing(TestBean bean){ - * "xxxxx" + bean; - * } - * } - * - * public final class _DynLocalTestService extends TestService{ - * - * @Resource - * private BsonConvert _convert; - * - * private Transport[] _sameGroupTransports; - * - * private Transport[] _diffGroupTransports; - * - * private SncpClient _client; - * - * private String _selfstring; - * - * @Override - * public final String name() { - * return ""; - * } - * - * @Override - * public String toString() { - * return _selfstring == null ? super.toString() : _selfstring; - * } - * - * @Override - * public String updateSomeThing(String id){ - * return _updateSomeThing(true, true, true, id); - * } - * - * public String _updateSomeThing(boolean canselfrun, boolean cansamerun, boolean candiffrun, String id){ - * String rs = super.updateSomeThing(id); - * if (_client== null) return; - * _client.remote(_convert, _sameGroupTransports, cansamerun, 0, true, false, false, id); - * _client.remote(_convert, _diffGroupTransports, candiffrun, 0, true, true, false, id); - * return rs; - * } - * - * @Override - * public void createSomeThing(TestBean bean){ - * _createSomeThing(false, true, true, bean); - * } - * - * public void _createSomeThing(boolean canselfrun, boolean cansamerun, boolean candiffrun, TestBean bean){ - * if(canselfrun) super.createSomeThing(bean); - * if (_client== null) return; - * _client.remote(_convert, _sameGroupTransports, cansamerun, 1, true, false, false, bean); - * _client.remote(_convert, _diffGroupTransports, candiffrun, 1, true, true, false, bean); - * } - * } - * - * 创建Service的本地模式Class - * @param - * @param name - * @param serviceClass - * @return - */ - @SuppressWarnings("unchecked") - public static Class createLocalServiceClass(final String name, final Class serviceClass) { - if (serviceClass == null) return null; - if (!Service.class.isAssignableFrom(serviceClass)) return serviceClass; - int mod = serviceClass.getModifiers(); - if (!java.lang.reflect.Modifier.isPublic(mod)) return serviceClass; - if (java.lang.reflect.Modifier.isAbstract(mod)) return serviceClass; - final List methods = SncpClient.parseMethod(serviceClass, false); - boolean hasMultiRun0 = false; - for (Method method : methods) { - if (method.getAnnotation(MultiRun.class) != null) { - hasMultiRun0 = true; - break; - } - } - final boolean hasMultiRun = hasMultiRun0; - final String supDynName = serviceClass.getName().replace('.', '/'); - final String clientName = SncpClient.class.getName().replace('.', '/'); - final String clientDesc = Type.getDescriptor(SncpClient.class); - final String convertDesc = Type.getDescriptor(BsonConvert.class); - final String sncpDynDesc = Type.getDescriptor(SncpDyn.class); - final String transportsDesc = Type.getDescriptor(Transport[].class); - ClassLoader loader = Sncp.class.getClassLoader(); - String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + LOCALPREFIX + serviceClass.getSimpleName(); - try { - return (Class) Class.forName(newDynName.replace('/', '.')); - } catch (Exception ex) { - } - //------------------------------------------------------------------------------ - ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); - FieldVisitor fv; - DebugMethodVisitor mv; - AnnotationVisitor av0; - - cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null); - { - av0 = cw.visitAnnotation(sncpDynDesc, true); - av0.visitEnd(); - } - if (hasMultiRun) { - { - fv = cw.visitField(ACC_PRIVATE, "_convert", convertDesc, null, null); - av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true); - av0.visitEnd(); - fv.visitEnd(); - } - { - fv = cw.visitField(ACC_PRIVATE, "_sameGroupTransports", transportsDesc, null, null); - fv.visitEnd(); - } - { - fv = cw.visitField(ACC_PRIVATE, "_diffGroupTransports", transportsDesc, null, null); - fv.visitEnd(); - } - { - fv = cw.visitField(ACC_PRIVATE, "_client", clientDesc, null, null); - fv.visitEnd(); - } - } - { - fv = cw.visitField(ACC_PRIVATE, "_selfstring", "Ljava/lang/String;", null, null); - fv.visitEnd(); - } - { //构造函数 - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC, "", "()V", null, null)); - //mv.setDebug(true); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, supDynName, "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - { // name() - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "name", "()Ljava/lang/String;", null, null)); - mv.visitLdcInsn(name); - mv.visitInsn(ARETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - { // toString() - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null)); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "_selfstring", "Ljava/lang/String;"); - Label l1 = new Label(); - mv.visitJumpInsn(IFNONNULL, l1); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false); - Label l2 = new Label(); - mv.visitJumpInsn(GOTO, l2); - mv.visitLabel(l1); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "_selfstring", "Ljava/lang/String;"); - mv.visitLabel(l2); - mv.visitInsn(ARETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - int i = - 1; - for (final Method method : methods) { - final MultiRun mrun = method.getAnnotation(MultiRun.class); - if (mrun == null) continue; - final Class returnType = method.getReturnType(); - final String methodDesc = Type.getMethodDescriptor(method); - final Class[] paramtypes = method.getParameterTypes(); - final int index = ++i; - { //原始方法 - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC + (method.isVarArgs() ? ACC_VARARGS : 0), method.getName(), methodDesc, null, null)); - //mv.setDebug(true); - { //给参数加上 Annotation - final Annotation[][] anns = method.getParameterAnnotations(); - for (int k = 0; k < anns.length; k++) { - for (Annotation ann : anns[k]) { - visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann); - } - } - } - mv.visitVarInsn(ALOAD, 0); - mv.visitInsn(mrun.selfrun() ? ICONST_1 : ICONST_0); - mv.visitInsn(mrun.samerun() ? ICONST_1 : ICONST_0); - mv.visitInsn(mrun.diffrun() ? ICONST_1 : ICONST_0); - int varindex = 0; - for (Class pt : paramtypes) { - if (pt.isPrimitive()) { - if (pt == long.class) { - mv.visitVarInsn(LLOAD, ++varindex); - ++varindex; - } else if (pt == double.class) { - mv.visitVarInsn(DLOAD, ++varindex); - ++varindex; - } else if (pt == float.class) { - mv.visitVarInsn(FLOAD, ++varindex); - } else { - mv.visitVarInsn(ILOAD, ++varindex); - } - } else { - mv.visitVarInsn(ALOAD, ++varindex); - } - } - mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "_" + method.getName(), "(ZZZ" + methodDesc.substring(1), false); - if (returnType == void.class) { - mv.visitInsn(RETURN); - } else if (returnType.isPrimitive()) { - if (returnType == long.class) { - mv.visitInsn(LRETURN); - } else if (returnType == float.class) { - mv.visitInsn(FRETURN); - } else if (returnType == double.class) { - mv.visitInsn(DRETURN); - } else { - mv.visitInsn(IRETURN); - } - } else { - mv.visitInsn(ARETURN); - } - mv.visitMaxs(varindex + 3, varindex + 1); - mv.visitEnd(); - } - { // _方法 - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC + (method.isVarArgs() ? ACC_VARARGS : 0), "_" + method.getName(), "(ZZZ" + methodDesc.substring(1), null, null)); - //mv.setDebug(true); - { //给参数加上 Annotation - final Annotation[][] anns = method.getParameterAnnotations(); - for (int k = 0; k < anns.length; k++) { - for (Annotation ann : anns[k]) { - visitAnnotation(mv.visitParameterAnnotation(k, Type.getDescriptor(ann.annotationType()), true), ann); - } - } - } - av0 = mv.visitAnnotation(sncpDynDesc, true); - av0.visit("index", index); - av0.visitEnd(); - Label l1 = new Label(); - if (returnType == void.class) { // if - mv.visitVarInsn(ILOAD, 1); - mv.visitJumpInsn(IFEQ, l1); - } - mv.visitVarInsn(ALOAD, 0); - int varindex = 3; - for (Class pt : paramtypes) { - if (pt.isPrimitive()) { - if (pt == long.class) { - mv.visitVarInsn(LLOAD, ++varindex); - ++varindex; - } else if (pt == double.class) { - mv.visitVarInsn(DLOAD, ++varindex); - ++varindex; - } else if (pt == float.class) { - mv.visitVarInsn(FLOAD, ++varindex); - } else { - mv.visitVarInsn(ILOAD, ++varindex); - } - } else { - mv.visitVarInsn(ALOAD, ++varindex); - } - } - mv.visitMethodInsn(INVOKESPECIAL, supDynName, method.getName(), methodDesc, false); - if (returnType == void.class) { // end if - mv.visitLabel(l1); - } - if (returnType == void.class) { - } else if (returnType.isPrimitive()) { - if (returnType == long.class) { - mv.visitVarInsn(LSTORE, ++varindex); - ++varindex; //多加1 - } else if (returnType == float.class) { - mv.visitVarInsn(FSTORE, ++varindex); - } else if (returnType == double.class) { - mv.visitVarInsn(DSTORE, ++varindex); - ++varindex; //多加1 - } else { - mv.visitVarInsn(ISTORE, ++varindex); - } - } else { - mv.visitVarInsn(ASTORE, ++varindex); - } - final int rsindex = varindex; // - - //---------------------------if (_client== null) return ---------------------------------- - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "_client", clientDesc); - Label ifrt = new Label(); - mv.visitJumpInsn(IFNONNULL, ifrt); - if (returnType == void.class) { - mv.visitInsn(RETURN); - } else if (returnType.isPrimitive()) { - if (returnType == long.class) { - mv.visitVarInsn(LLOAD, rsindex); - mv.visitInsn(LRETURN); - } else if (returnType == float.class) { - mv.visitVarInsn(FLOAD, rsindex); - mv.visitInsn(FRETURN); - } else if (returnType == double.class) { - mv.visitVarInsn(DLOAD, rsindex); - mv.visitInsn(DRETURN); - } else { - mv.visitVarInsn(ILOAD, rsindex); - mv.visitInsn(IRETURN); - } - } else { - mv.visitVarInsn(ALOAD, rsindex); - mv.visitInsn(ARETURN); - } - mv.visitLabel(ifrt); - //------------------------------------------------------------- - mv.visitVarInsn(ALOAD, 0);//调用 _client - mv.visitFieldInsn(GETFIELD, newDynName, "_client", clientDesc); - mv.visitVarInsn(ALOAD, 0); //传递 _convert - mv.visitFieldInsn(GETFIELD, newDynName, "_convert", convertDesc); - mv.visitVarInsn(ALOAD, 0); //传递 _sameGroupTransports - mv.visitFieldInsn(GETFIELD, newDynName, "_sameGroupTransports", transportsDesc); - - mv.visitVarInsn(ILOAD, 2); //传递 cansamerun - - if (index <= 5) { //第几个 SncpAction - mv.visitInsn(ICONST_0 + index); - } else { - mv.visitIntInsn(BIPUSH, index); - } - if (paramtypes.length + 3 <= 5) { //参数总数量 - mv.visitInsn(ICONST_0 + paramtypes.length + 3); - } else { - mv.visitIntInsn(BIPUSH, paramtypes.length + 3); - } - - mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); - - mv.visitInsn(DUP); - mv.visitInsn(ICONST_0); - mv.visitInsn(ICONST_1); //第一个参数 canselfrun - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - mv.visitInsn(AASTORE); - - mv.visitInsn(DUP); - mv.visitInsn(ICONST_1); - mv.visitInsn(ICONST_0); //第一个参数 cansamerun - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - mv.visitInsn(AASTORE); - - mv.visitInsn(DUP); - mv.visitInsn(ICONST_2); - mv.visitInsn(ICONST_0); //第二个参数 candiffrun - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - mv.visitInsn(AASTORE); - - int insn = 3; - for (int j = 0; j < paramtypes.length; j++) { - final Class pt = paramtypes[j]; - mv.visitInsn(DUP); - insn++; - if (j <= 2) { - mv.visitInsn(ICONST_0 + j + 3); - } else { - mv.visitIntInsn(BIPUSH, j + 3); - } - if (pt.isPrimitive()) { - if (pt == long.class) { - mv.visitVarInsn(LLOAD, insn++); - } else if (pt == float.class) { - mv.visitVarInsn(FLOAD, insn++); - } else if (pt == double.class) { - mv.visitVarInsn(DLOAD, insn++); - } else { - mv.visitVarInsn(ILOAD, insn); - } - Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(pt, 1), 0).getClass(); - mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor(pt) + ")" + Type.getDescriptor(bigclaz), false); - } else { - mv.visitVarInsn(ALOAD, insn); - } - mv.visitInsn(AASTORE); - } - mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemote" : "remote", "(" + convertDesc + transportsDesc + "ZI[Ljava/lang/Object;)V", false); - - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "_client", clientDesc); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "_convert", convertDesc); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "_diffGroupTransports", transportsDesc); - - mv.visitVarInsn(ILOAD, 3); //传递 candiffrun - if (index <= 5) { //第几个 SncpAction - mv.visitInsn(ICONST_0 + index); - } else { - mv.visitIntInsn(BIPUSH, index); - } - if (paramtypes.length + 3 <= 5) { //参数总数量 - mv.visitInsn(ICONST_0 + paramtypes.length + 3); - } else { - mv.visitIntInsn(BIPUSH, paramtypes.length + 3); - } - - mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); - - mv.visitInsn(DUP); - mv.visitInsn(ICONST_0); - mv.visitInsn(ICONST_1); //第一个参数 cansamerun - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - mv.visitInsn(AASTORE); - - mv.visitInsn(DUP); - mv.visitInsn(ICONST_1); - mv.visitInsn(ICONST_1); //第二个参数 candiffrun - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - mv.visitInsn(AASTORE); - - mv.visitInsn(DUP); - mv.visitInsn(ICONST_2); - mv.visitInsn(ICONST_0); //第二个参数 candiffrun - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - mv.visitInsn(AASTORE); - - insn = 3; - for (int j = 0; j < paramtypes.length; j++) { - final Class pt = paramtypes[j]; - mv.visitInsn(DUP); - insn++; - if (j <= 2) { - mv.visitInsn(ICONST_0 + j + 3); - } else { - mv.visitIntInsn(BIPUSH, j + 3); - } - if (pt.isPrimitive()) { - if (pt == long.class) { - mv.visitVarInsn(LLOAD, insn++); - } else if (pt == float.class) { - mv.visitVarInsn(FLOAD, insn++); - } else if (pt == double.class) { - mv.visitVarInsn(DLOAD, insn++); - } else { - mv.visitVarInsn(ILOAD, insn); - } - Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(pt, 1), 0).getClass(); - mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor(pt) + ")" + Type.getDescriptor(bigclaz), false); - } else { - mv.visitVarInsn(ALOAD, insn); - } - mv.visitInsn(AASTORE); - } - mv.visitMethodInsn(INVOKEVIRTUAL, clientName, mrun.async() ? "asyncRemote" : "remote", "(" + convertDesc + transportsDesc + "ZI[Ljava/lang/Object;)V", false); - - if (returnType == void.class) { - mv.visitInsn(RETURN); - } else if (returnType.isPrimitive()) { - if (returnType == long.class) { - mv.visitVarInsn(LLOAD, rsindex); - mv.visitInsn(LRETURN); - } else if (returnType == float.class) { - mv.visitVarInsn(FLOAD, rsindex); - mv.visitInsn(FRETURN); - } else if (returnType == double.class) { - mv.visitVarInsn(DLOAD, rsindex); - mv.visitInsn(DRETURN); - } else { - mv.visitVarInsn(ILOAD, rsindex); - mv.visitInsn(IRETURN); - } - } else { - mv.visitVarInsn(ALOAD, rsindex); - mv.visitInsn(ARETURN); - } - - mv.visitMaxs(Math.max(varindex, 10), varindex + 4); - mv.visitEnd(); - } - } - cw.visitEnd(); - byte[] bytes = cw.toByteArray(); - Class newClazz = new ClassLoader(loader) { - public final Class loadClass(String name, byte[] b) { - return defineClass(name, b, 0, b.length); - } - }.loadClass(newDynName.replace('/', '.'), bytes); - return (Class) newClazz; - } - - private static void visitAnnotation(final AnnotationVisitor av, final Annotation ann) { - try { - for (Method anm : ann.annotationType().getMethods()) { - final String mname = anm.getName(); - if ("equals".equals(mname) || "hashCode".equals(mname) || "toString".equals(mname) || "annotationType".equals(mname)) continue; - final Object r = anm.invoke(ann); - if (r instanceof String[]) { - AnnotationVisitor av1 = av.visitArray(mname); - for (String item : (String[]) r) { - av1.visit(null, item); - } - av1.visitEnd(); - } else if (r instanceof Class[]) { - AnnotationVisitor av1 = av.visitArray(mname); - for (Class item : (Class[]) r) { - av1.visit(null, Type.getType(item)); - } - av1.visitEnd(); - } else if (r instanceof Enum[]) { - AnnotationVisitor av1 = av.visitArray(mname); - for (Enum item : (Enum[]) r) { - av1.visitEnum(null, Type.getDescriptor(item.getClass()), ((Enum) item).name()); - } - av1.visitEnd(); - } else if (r instanceof Annotation[]) { - AnnotationVisitor av1 = av.visitArray(mname); - for (Annotation item : (Annotation[]) r) { - visitAnnotation(av1.visitAnnotation(null, Type.getDescriptor(((Annotation) item).annotationType())), item); - } - av1.visitEnd(); - } else if (r instanceof Class) { - av.visit(mname, Type.getType((Class) r)); - } else if (r instanceof Enum) { - av.visitEnum(mname, Type.getDescriptor(r.getClass()), ((Enum) r).name()); - } else if (r instanceof Annotation) { - visitAnnotation(av.visitAnnotation(null, Type.getDescriptor(((Annotation) r).annotationType())), (Annotation) r); - } else { - av.visit(mname, r); - } - } - av.visitEnd(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * - * 创建本地模式Service实例 - * - * @param - * @param name - * @param executor - * @param serviceClass - * @param clientAddress - * @param groups - * @param sameGroupTransports - * @param diffGroupTransports - * @return - */ - @SuppressWarnings("unchecked") - public static T createLocalService( - final String name, - final Consumer executor, - final Class serviceClass, - final InetSocketAddress clientAddress, HashSet groups, Collection sameGroupTransports, Collection diffGroupTransports - ) { - try { - final Class newClazz = createLocalServiceClass(name, serviceClass); - T rs = (T) newClazz.newInstance(); - //-------------------------------------- - if (sameGroupTransports == null) sameGroupTransports = new ArrayList<>(); - if (diffGroupTransports == null) diffGroupTransports = new ArrayList<>(); - Transport remoteTransport = null; - { - Class loop = newClazz; - String[] groupArray = null; - do { - for (Field field : loop.getDeclaredFields()) { - int mod = field.getModifiers(); - if (Modifier.isFinal(mod) || Modifier.isStatic(mod)) continue; - if (field.getAnnotation(SncpRemote.class) != null) { - field.setAccessible(true); - if (remoteTransport == null) { - List list = new ArrayList<>(); - list.addAll(sameGroupTransports); - list.addAll(diffGroupTransports); - if (!list.isEmpty()) remoteTransport = new Transport(list.get(0), clientAddress, list); - } - if (field.getType().isAssignableFrom(newClazz) && remoteTransport != null) { - field.set(rs, createRemoteService(name, executor, serviceClass, clientAddress, groups, remoteTransport)); - } - continue; - } - Resource res = field.getAnnotation(Resource.class); - if (res == null) continue; - field.setAccessible(true); - if (res.name().equals(RESNAME_SNCP_GROUPS)) { - if (groups == null) groups = new LinkedHashSet<>(); - if (groupArray == null) groupArray = groups.toArray(new String[groups.size()]); - if (field.getGenericType().equals(GROUPS_TYPE1)) { - field.set(rs, groups); - } else if (field.getGenericType().equals(GROUPS_TYPE2)) { - field.set(rs, groupArray); - } - } else if (res.name().endsWith(RESNAME_SNCP_ADDR)) { - if (field.getType() == String.class) { - field.set(rs, clientAddress == null ? null : (clientAddress.getHostString() + ":" + clientAddress.getPort())); - } else { - field.set(rs, clientAddress); - } - } - } - } while ((loop = loop.getSuperclass()) != Object.class); - } - SncpClient client = null; - { - try { - Field e = newClazz.getDeclaredField("_client"); - e.setAccessible(true); - client = new SncpClient(name, executor, hash(serviceClass), false, newClazz, true, clientAddress, groups); - e.set(rs, client); - } catch (NoSuchFieldException ne) { - } - } - { - StringBuilder sb = new StringBuilder(); - sb.append(newClazz.getName()).append("{name = ").append(name); - if (client != null) { - sb.append(", nameid = ").append(client.getNameid()).append(", serviceid = ").append(client.getServiceid()); - sb.append(", action.size = ").append(client.getActionCount()); - - sb.append(", address = ").append(clientAddress).append(", groups = ").append(groups); - List addrs = new ArrayList<>(); - for (Transport t : sameGroupTransports) { - addrs.addAll(Arrays.asList(t.getRemoteAddress())); - } - sb.append(", samegroups = ").append(addrs); - - addrs.clear(); - for (Transport t : diffGroupTransports) { - addrs.addAll(Arrays.asList(t.getRemoteAddress())); - } - sb.append(", diffgroups = ").append(addrs); - } else { - sb.append(", ").append(MultiRun.class.getSimpleName().toLowerCase()).append(" = false"); - } - sb.append("}"); - Field s = newClazz.getDeclaredField("_selfstring"); - s.setAccessible(true); - s.set(rs, sb.toString()); - } - if (client == null) return rs; - { - Field c = newClazz.getDeclaredField("_sameGroupTransports"); - c.setAccessible(true); - c.set(rs, sameGroupTransports.toArray(new Transport[sameGroupTransports.size()])); - } - { - Field t = newClazz.getDeclaredField("_diffGroupTransports"); - t.setAccessible(true); - t.set(rs, diffGroupTransports.toArray(new Transport[diffGroupTransports.size()])); - } - return rs; - } catch (RuntimeException rex) { - throw rex; - } catch (Exception ex) { - throw new RuntimeException(ex); - } - - } - - /** - * public final class _DynRemoteTestService extends TestService{ - * - * @Resource - * private BsonConvert _convert; - * - * private Transport _transport; - * - * private SncpClient _client; - * - * private String _selfstring; - * - * @Override - * public final String name() { - * return ""; - * } - * - * @Override - * public String toString() { - * return _selfstring == null ? super.toString() : _selfstring; - * } - * - * @Override - * public boolean testChange(TestBean bean) { - * return _client.remote(_convert, _transport, 0, bean); - * } - * - * @Override - * public TestBean findTestBean(long id) { - * return _client.remote(_convert, _transport, 1, id); - * } - * - * @Override - * public void runTestBean(long id, TestBean bean) { - * _client.remote(_convert, _transport, 2, id, bean); - * } - * } - * - * 创建远程模式的Service实例 - *

- * @param - * @param name - * @param executor - * @param serviceClass - * @param clientAddress - * @param groups - * @param transport - * @return - */ - @SuppressWarnings("unchecked") - public static T createRemoteService( - final String name, - final Consumer executor, - final Class serviceClass, - final InetSocketAddress clientAddress, HashSet groups, final Transport transport - ) { - if (serviceClass == null) return null; - if (!Service.class.isAssignableFrom(serviceClass)) return null; - int mod = serviceClass.getModifiers(); - if (!java.lang.reflect.Modifier.isPublic(mod)) return null; - if (java.lang.reflect.Modifier.isAbstract(mod)) return null; - final String supDynName = serviceClass.getName().replace('.', '/'); - final String clientName = SncpClient.class.getName().replace('.', '/'); - final String clientDesc = Type.getDescriptor(SncpClient.class); - final String sncpDynDesc = Type.getDescriptor(SncpDyn.class); - final String convertDesc = Type.getDescriptor(BsonConvert.class); - final String transportDesc = Type.getDescriptor(Transport.class); - final String anyValueDesc = Type.getDescriptor(AnyValue.class); - ClassLoader loader = Sncp.class.getClassLoader(); - String newDynName = supDynName.substring(0, supDynName.lastIndexOf('/') + 1) + REMOTEPREFIX + serviceClass.getSimpleName(); - final SncpClient client = new SncpClient(name, executor, hash(serviceClass), true, createLocalServiceClass(name, serviceClass), false, clientAddress, groups); - try { - Class newClazz = Class.forName(newDynName.replace('/', '.')); - T rs = (T) newClazz.newInstance(); - Field c = newClazz.getDeclaredField("_client"); - c.setAccessible(true); - c.set(rs, client); - Field t = newClazz.getDeclaredField("_transport"); - t.setAccessible(true); - t.set(rs, transport); - { - StringBuilder sb = new StringBuilder(); - sb.append(newClazz.getName()).append("{name = ").append(name); - sb.append(", nameid = ").append(client.getNameid()).append(", serviceid = ").append(client.getServiceid()); - sb.append(", action.size = ").append(client.getActionCount()); - sb.append(", address = ").append(clientAddress).append(", groups = ").append(groups); - sb.append(", remotes = ").append(transport == null ? null : Arrays.asList(transport.getRemoteAddress())); - sb.append("}"); - Field s = newClazz.getDeclaredField("_selfstring"); - s.setAccessible(true); - s.set(rs, sb.toString()); - } - return rs; - } catch (Exception ex) { - } - //------------------------------------------------------------------------------ - ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); - FieldVisitor fv; - DebugMethodVisitor mv; - AnnotationVisitor av0; - - cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null); - { - av0 = cw.visitAnnotation(sncpDynDesc, true); - av0.visitEnd(); - } - { - fv = cw.visitField(ACC_PRIVATE, "_convert", convertDesc, null, null); - av0 = fv.visitAnnotation("Ljavax/annotation/Resource;", true); - av0.visitEnd(); - fv.visitEnd(); - } - { - fv = cw.visitField(ACC_PRIVATE, "_transport", transportDesc, null, null); - fv.visitEnd(); - } - { - fv = cw.visitField(ACC_PRIVATE, "_client", clientDesc, null, null); - fv.visitEnd(); - } - { - fv = cw.visitField(ACC_PRIVATE, "_selfstring", "Ljava/lang/String;", null, null); - fv.visitEnd(); - } - { //构造函数 - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC, "", "()V", null, null)); - //mv.setDebug(true); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, supDynName, "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - { //init - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC, "init", "(" + anyValueDesc + ")V", null, null)); - mv.visitInsn(RETURN); - mv.visitMaxs(0, 2); - mv.visitEnd(); - } - { //destroy - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC, "destroy", "(" + anyValueDesc + ")V", null, null)); - mv.visitInsn(RETURN); - mv.visitMaxs(0, 2); - mv.visitEnd(); - } - { // name() - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "name", "()Ljava/lang/String;", null, null)); - mv.visitLdcInsn(name); - mv.visitInsn(ARETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - { // toString() - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null)); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "_selfstring", "Ljava/lang/String;"); - Label l1 = new Label(); - mv.visitJumpInsn(IFNONNULL, l1); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false); - Label l2 = new Label(); - mv.visitJumpInsn(GOTO, l2); - mv.visitLabel(l1); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "_selfstring", "Ljava/lang/String;"); - mv.visitLabel(l2); - mv.visitInsn(ARETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - int i = -1; - for (final SncpAction entry : client.actions) { - final int index = ++i; - final java.lang.reflect.Method method = entry.method; - { - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC, method.getName(), Type.getMethodDescriptor(method), null, null)); - //mv.setDebug(true); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "_client", clientDesc); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "_convert", convertDesc); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "_transport", transportDesc); - if (index <= 5) { - mv.visitInsn(ICONST_0 + index); - } else { - mv.visitIntInsn(BIPUSH, index); - } - - { //传参数 - int paramlen = entry.paramTypes.length; - if (paramlen <= 5) { - mv.visitInsn(ICONST_0 + paramlen); - } else { - mv.visitIntInsn(BIPUSH, paramlen); - } - mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); - java.lang.reflect.Type[] paramtypes = entry.paramTypes; - int insn = 0; - for (int j = 0; j < paramtypes.length; j++) { - final java.lang.reflect.Type pt = paramtypes[j]; - mv.visitInsn(DUP); - insn++; - if (j <= 5) { - mv.visitInsn(ICONST_0 + j); - } else { - mv.visitIntInsn(BIPUSH, j); - } - if (pt instanceof Class && ((Class) pt).isPrimitive()) { - if (pt == long.class) { - mv.visitVarInsn(LLOAD, insn++); - } else if (pt == float.class) { - mv.visitVarInsn(FLOAD, insn++); - } else if (pt == double.class) { - mv.visitVarInsn(DLOAD, insn++); - } else { - mv.visitVarInsn(ILOAD, insn); - } - Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance((Class) pt, 1), 0).getClass(); - mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor((Class) pt) + ")" + Type.getDescriptor(bigclaz), false); - } else { - mv.visitVarInsn(ALOAD, insn); - } - mv.visitInsn(AASTORE); - } - } - - mv.visitMethodInsn(INVOKEVIRTUAL, clientName, "remote", "(" + convertDesc + transportDesc + "I[Ljava/lang/Object;)Ljava/lang/Object;", false); - //mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false); - if (method.getGenericReturnType() == void.class) { - mv.visitInsn(POP); - mv.visitInsn(RETURN); - } else { - Class returnclz = method.getReturnType(); - Class bigPrimitiveClass = returnclz.isPrimitive() ? java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(returnclz, 1), 0).getClass() : returnclz; - mv.visitTypeInsn(CHECKCAST, (returnclz.isPrimitive() ? bigPrimitiveClass : returnclz).getName().replace('.', '/')); - if (returnclz.isPrimitive()) { - String bigPrimitiveName = bigPrimitiveClass.getName().replace('.', '/'); - try { - java.lang.reflect.Method pm = bigPrimitiveClass.getMethod(returnclz.getSimpleName() + "Value"); - mv.visitMethodInsn(INVOKEVIRTUAL, bigPrimitiveName, pm.getName(), Type.getMethodDescriptor(pm), false); - } catch (Exception ex) { - throw new RuntimeException(ex); //不可能会发生 - } - if (returnclz == long.class) { - mv.visitInsn(LRETURN); - } else if (returnclz == float.class) { - mv.visitInsn(FRETURN); - } else if (returnclz == double.class) { - mv.visitInsn(DRETURN); - } else { - mv.visitInsn(IRETURN); - } - } else { - mv.visitInsn(ARETURN); - } - } - mv.visitMaxs(20, 20); - mv.visitEnd(); - } - } - cw.visitEnd(); - byte[] bytes = cw.toByteArray(); - Class newClazz = new ClassLoader(loader) { - public final Class loadClass(String name, byte[] b) { - return defineClass(name, b, 0, b.length); - } - }.loadClass(newDynName.replace('/', '.'), bytes); - try { - T rs = (T) newClazz.newInstance(); - Field c = newClazz.getDeclaredField("_client"); - c.setAccessible(true); - c.set(rs, client); - Field t = newClazz.getDeclaredField("_transport"); - t.setAccessible(true); - t.set(rs, transport); - { - StringBuilder sb = new StringBuilder(); - sb.append(newClazz.getName()).append("{name = ").append(name); - sb.append(", nameid = ").append(client.getNameid()).append(", serviceid = ").append(client.getServiceid()); - sb.append(", action.size = ").append(client.getActionCount()); - sb.append(", address = ").append(clientAddress).append(", groups = ").append(groups); - sb.append(", remotes = ").append(transport == null ? null : Arrays.asList(transport.getRemoteAddress())); - sb.append("}"); - Field s = newClazz.getDeclaredField("_selfstring"); - s.setAccessible(true); - s.set(rs, sb.toString()); - } - return rs; - } catch (Exception ex) { - throw new RuntimeException(ex); - } - - } -} diff --git a/src/com/wentch/redkale/net/sncp/SncpCall.java b/src/com/wentch/redkale/net/sncp/SncpCall.java deleted file mode 100644 index eb745eb3d..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpCall.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import com.wentch.redkale.util.*; -import java.lang.annotation.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * 参数回写, 当Service的方法需要更改参数对象内部的数据时,需要使用SncpCall - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({ElementType.PARAMETER}) -@Retention(RUNTIME) -public @interface SncpCall { - - Class value(); -} diff --git a/src/com/wentch/redkale/net/sncp/SncpClient.java b/src/com/wentch/redkale/net/sncp/SncpClient.java deleted file mode 100644 index b26453a98..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpClient.java +++ /dev/null @@ -1,406 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import com.wentch.redkale.convert.bson.*; -import com.wentch.redkale.convert.json.*; -import com.wentch.redkale.net.*; -import static com.wentch.redkale.net.sncp.SncpRequest.*; -import com.wentch.redkale.util.*; -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.net.*; -import java.nio.*; -import java.nio.channels.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.function.*; -import java.util.logging.*; - -/** - * - * @author zhangjx - */ -public final class SncpClient { - - protected static final class SncpAction { - - protected final DLong actionid; - - protected final Method method; - - protected final Type resultTypes; //void 必须设为 null - - protected final Type[] paramTypes; - - protected final Attribute[] paramAttrs; // 为null表示无SncpCall处理,index=0固定为null, 其他为参数标记的SncpCall回调方法 - - protected final int addressParamIndex; - - public SncpAction(Method method, DLong actionid) { - this.actionid = actionid; - Type rt = method.getGenericReturnType(); - if (rt instanceof TypeVariable) { - TypeVariable tv = (TypeVariable) rt; - if (tv.getBounds().length == 1) rt = tv.getBounds()[0]; - } - this.resultTypes = rt == void.class ? null : rt; - this.paramTypes = method.getGenericParameterTypes(); - this.method = method; - Annotation[][] anns = method.getParameterAnnotations(); - int addrIndex = -1; - boolean hasattr = false; - Attribute[] atts = new Attribute[paramTypes.length + 1]; - if (anns.length > 0) { - Class[] params = method.getParameterTypes(); - for (int i = 0; i < anns.length; i++) { - if (anns[i].length > 0) { - for (Annotation ann : anns[i]) { - if (ann.annotationType() == SncpTargetAddress.class && SocketAddress.class.isAssignableFrom(params[i])) { - addrIndex = i; - break; - } - } - for (Annotation ann : anns[i]) { - if (ann.annotationType() == SncpCall.class) { - try { - atts[i + 1] = ((SncpCall) ann).value().newInstance(); - hasattr = true; - } catch (Exception e) { - logger.log(Level.SEVERE, SncpCall.class.getSimpleName() + ".attribute cannot a newInstance for" + method, e); - } - break; - } - } - } - } - } - this.addressParamIndex = addrIndex; - this.paramAttrs = hasattr ? atts : null; - } - - @Override - public String toString() { - return "{" + actionid + "," + (method == null ? "null" : method.getName()) + "}"; - } - } - - private static final Logger logger = Logger.getLogger(SncpClient.class.getSimpleName()); - - private final boolean finest = logger.isLoggable(Level.FINEST); - - protected final JsonConvert jsonConvert = JsonFactory.root().getConvert(); - - protected final String name; - - protected final boolean remote; - - private final Class serviceClass; - - protected final InetSocketAddress address; - - protected final HashSet groups; - - private final byte[] addrBytes; - - private final int addrPort; - - protected final long nameid; - - protected final long serviceid; - - protected final SncpAction[] actions; - - protected final Consumer executor; - - public SncpClient(final String serviceName, final Consumer executor, final long serviceid0, boolean remote, final Class serviceClass, - boolean onlySncpDyn, final InetSocketAddress clientAddress, final HashSet groups) { - if (serviceName.length() > 10) throw new RuntimeException(serviceClass + " @Resource name(" + serviceName + ") too long , must less 11"); - this.remote = remote; - this.executor = executor; - this.serviceClass = serviceClass; - this.address = clientAddress; - this.groups = groups; - //if (subLocalClass != null && !serviceClass.isAssignableFrom(subLocalClass)) throw new RuntimeException(subLocalClass + " is not " + serviceClass + " sub class "); - this.name = serviceName; - this.nameid = Sncp.hash(serviceName); - this.serviceid = serviceid0 > 0 ? serviceid0 : Sncp.hash(serviceClass); - final List methodens = new ArrayList<>(); - //------------------------------------------------------------------------------ - for (java.lang.reflect.Method method : parseMethod(serviceClass, onlySncpDyn)) { - SncpAction en = new SncpAction(method, Sncp.hash(method)); - methodens.add(en); - } - this.actions = methodens.toArray(new SncpAction[methodens.size()]); - this.addrBytes = clientAddress == null ? new byte[4] : clientAddress.getAddress().getAddress(); - this.addrPort = clientAddress == null ? 0 : clientAddress.getPort(); - } - - public long getNameid() { - return nameid; - } - - public long getServiceid() { - return serviceid; - } - - public int getActionCount() { - return actions.length; - } - - @Override - public String toString() { - String service = serviceClass.getName(); - if (remote) service = service.replace(Sncp.LOCALPREFIX, Sncp.REMOTEPREFIX); - return this.getClass().getSimpleName() + "(service = " + service + ", serviceid = " + serviceid - + ", name = " + name + ", nameid = " + nameid + ", address = " + (address == null ? "" : (address.getHostString() + ":" + address.getPort())) - + ", groups = " + groups + ", actions.size = " + actions.length + ")"; - } - - public static List parseMethod(final Class serviceClass, boolean onlySncpDyn) { - final List list = new ArrayList<>(); - final List multis = new ArrayList<>(); - final Map actionids = new HashMap<>(); - - for (final java.lang.reflect.Method method : serviceClass.getMethods()) { - if (method.isSynthetic()) continue; - final int mod = method.getModifiers(); - if (Modifier.isStatic(mod)) continue; - if (Modifier.isFinal(mod)) continue; - if (method.getName().equals("getClass") || method.getName().equals("toString")) continue; - if (method.getName().equals("equals") || method.getName().equals("hashCode")) continue; - if (method.getName().equals("notify") || method.getName().equals("notifyAll") || method.getName().equals("wait")) continue; - if (method.getName().equals("init") || method.getName().equals("destroy") || method.getName().equals("name")) continue; - if (onlySncpDyn && method.getAnnotation(SncpDyn.class) == null) continue; - DLong actionid = Sncp.hash(method); - Method old = actionids.get(actionid); - if (old != null) { - if (old.getDeclaringClass().equals(method.getDeclaringClass())) - throw new RuntimeException(serviceClass.getName() + " have one more same action(Method=" + method + ", " + old + ", actionid=" + actionid + ")"); - continue; - } - actionids.put(actionid, method); - if (method.getAnnotation(SncpDyn.class) != null) { - multis.add(method); - } else { - list.add(method); - } - } - list.addAll(multis); - if (onlySncpDyn && list.size() > 1) { - list.sort((m1, m2) -> m1.getAnnotation(SncpDyn.class).index() - m2.getAnnotation(SncpDyn.class).index()); - } - return list; - } - - public T remote(final BsonConvert convert, Transport transport, final int index, final Object... params) { - Future future = remote(convert, transport, actions[index], params); - final BsonReader in = convert.pollBsonReader(); - try { - final SncpAction action = actions[index]; - in.setBytes(future.get(5, TimeUnit.SECONDS)); - byte i; - while ((i = in.readByte()) != 0) { - final Attribute attr = action.paramAttrs[i]; - attr.set(params[i - 1], convert.convertFrom(in, attr.type())); - } - return convert.convertFrom(in, action.resultTypes); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - logger.log(Level.SEVERE, actions[index].method + " sncp (params: " + jsonConvert.convertTo(params) + ") remote error", e); - throw new RuntimeException(actions[index].method + " sncp remote error", e); - } finally { - convert.offerBsonReader(in); - } - } - - public void remote(final BsonConvert convert, Transport[] transports, boolean run, final int index, final Object... params) { - if (!run || transports == null || transports.length < 1) return; - remote(convert, transports[0], index, params); - for (int i = 1; i < transports.length; i++) { - remote(convert, transports[i], actions[index], params); - } - } - - public void asyncRemote(final BsonConvert convert, Transport[] transports, boolean run, final int index, final Object... params) { - if (!run || transports == null || transports.length < 1) return; - if (executor != null) { - executor.accept(() -> { - remote(convert, transports[0], index, params); - for (int i = 1; i < transports.length; i++) { - remote(convert, transports[i], actions[index], params); - } - }); - } else { - remote(convert, transports[0], index, params); - for (int i = 1; i < transports.length; i++) { - remote(convert, transports[i], actions[index], params); - } - } - } - - private Future remote(final BsonConvert convert, final Transport transport, final SncpAction action, final Object... params) { - Type[] myparamtypes = action.paramTypes; - final BsonWriter writer = convert.pollBsonWriter(transport.getBufferSupplier()); // 将head写入 - writer.writeTo(DEFAULT_HEADER); - for (int i = 0; i < params.length; i++) { - convert.convertTo(writer, myparamtypes[i], params[i]); - } - final int reqBodyLength = writer.count() - HEADER_SIZE; //body总长度 - final long seqid = System.nanoTime(); - final DLong actionid = action.actionid; - final SocketAddress addr = action.addressParamIndex >= 0 ? (SocketAddress) params[action.addressParamIndex] : null; - final AsyncConnection conn = transport.pollConnection(addr); - if (conn == null || !conn.isOpen()) { - logger.log(Level.SEVERE, action.method + " sncp (params: " + jsonConvert.convertTo(params) + ") cannot connect " + (conn == null ? addr : conn.getRemoteAddress())); - throw new RuntimeException("sncp " + (conn == null ? addr : conn.getRemoteAddress()) + " cannot connect"); - } - final ByteBuffer[] sendBuffers = writer.toBuffers(); - fillHeader(sendBuffers[0], seqid, actionid, reqBodyLength, 0, reqBodyLength); - - final ByteBuffer buffer = transport.pollBuffer(); - final SncpFuture future = new SncpFuture(); - conn.write(sendBuffers, sendBuffers, new CompletionHandler() { - - @Override - public void completed(Integer result, ByteBuffer[] attachments) { - int index = -1; - for (int i = 0; i < attachments.length; i++) { - if (attachments[i].hasRemaining()) { - index = i; - break; - } else { - transport.offerBuffer(attachments[i]); - } - } - if (index == 0) { - conn.write(attachments, attachments, this); - return; - } else if (index > 0) { - ByteBuffer[] newattachs = new ByteBuffer[attachments.length - index]; - System.arraycopy(attachments, index, newattachs, 0, newattachs.length); - conn.write(newattachs, newattachs, this); - return; - } - //----------------------- 读取返回结果 ------------------------------------- - buffer.clear(); - conn.read(buffer, null, new CompletionHandler() { - - private byte[] body; - - private int received; - - @Override - public void completed(Integer count, Void attachment2) { - if (count < 1 && buffer.remaining() == buffer.limit()) { //没有数据可读 - future.set(new RuntimeException(action.method + " sncp[" + conn.getRemoteAddress() + "] remote no response data")); - transport.offerBuffer(buffer); - transport.offerConnection(true, conn); - return; - } - if (received < 1 && buffer.limit() < buffer.remaining() + HEADER_SIZE) { //header都没读全 - conn.read(buffer, attachment2, this); - return; - } - buffer.flip(); - if (received > 0) { - int offset = this.received; - this.received += buffer.remaining(); - buffer.get(body, offset, Math.min(buffer.remaining(), this.body.length - offset)); - if (this.received < this.body.length) {// 数据仍然不全,需要继续读取 - buffer.clear(); - conn.read(buffer, attachment2, this); - } else { - success(); - } - return; - } - checkResult(seqid, action, buffer); - - final int respBodyLength = buffer.getInt(); - buffer.getInt(); // bodyOffset - buffer.getInt(); // frameLength - final int retcode = buffer.getInt(); - if (retcode != 0) { - logger.log(Level.SEVERE, action.method + " sncp (params: " + jsonConvert.convertTo(params) + ") deal error (retcode=" + retcode + ", retinfo=" + SncpResponse.getRetCodeInfo(retcode) + ")"); - throw new RuntimeException("remote service(" + action.method + ") deal error (retcode=" + retcode + ", retinfo=" + SncpResponse.getRetCodeInfo(retcode) + ")"); - } - - if (respBodyLength > buffer.remaining()) { // 数据不全,需要继续读取 - this.body = new byte[respBodyLength]; - this.received = buffer.remaining(); - buffer.get(body, 0, this.received); - buffer.clear(); - conn.read(buffer, attachment2, this); - } else { - this.body = new byte[respBodyLength]; - buffer.get(body, 0, respBodyLength); - success(); - } - } - - public void success() { - future.set(this.body); - transport.offerBuffer(buffer); - transport.offerConnection(false, conn); - } - - @Override - public void failed(Throwable exc, Void attachment2) { - logger.log(Level.SEVERE, action.method + " sncp (params: " + jsonConvert.convertTo(params) + ") remote read exec failed", exc); - future.set(new RuntimeException(action.method + " sncp remote exec failed")); - transport.offerBuffer(buffer); - transport.offerConnection(true, conn); - } - }); - } - - @Override - public void failed(Throwable exc, ByteBuffer[] attachment) { - logger.log(Level.SEVERE, action.method + " sncp (params: " + jsonConvert.convertTo(params) + ") remote write exec failed", exc); - transport.offerBuffer(buffer); - transport.offerConnection(true, conn); - } - }); - return future; - } - - private void checkResult(long seqid, final SncpAction action, ByteBuffer buffer) { - long rseqid = buffer.getLong(); - if (rseqid != seqid) throw new RuntimeException("sncp(" + action.method + ") response.seqid = " + seqid + ", but request.seqid =" + rseqid); - if (buffer.getChar() != HEADER_SIZE) throw new RuntimeException("sncp(" + action.method + ") buffer receive header.length not " + HEADER_SIZE); - long rserviceid = buffer.getLong(); - if (rserviceid != serviceid) throw new RuntimeException("sncp(" + action.method + ") response.serviceid = " + serviceid + ", but request.serviceid =" + rserviceid); - long rnameid = buffer.getLong(); - if (rnameid != nameid) throw new RuntimeException("sncp(" + action.method + ") response.nameid = " + nameid + ", but receive nameid =" + rnameid); - long ractionid1 = buffer.getLong(); - long ractionid2 = buffer.getLong(); - if (!action.actionid.equals(ractionid1, ractionid2)) throw new RuntimeException("sncp(" + action.method + ") response.actionid = " + action.actionid + ", but request.actionid =(" + ractionid1 + "_" + ractionid2 + ")"); - buffer.getInt(); //地址 - buffer.getChar(); //端口 - } - - private void fillHeader(ByteBuffer buffer, long seqid, DLong actionid, int bodyLength, int bodyOffset, int frameLength) { - //---------------------head---------------------------------- - final int currentpos = buffer.position(); - buffer.position(0); - buffer.putLong(seqid); //序列号 - buffer.putChar((char) HEADER_SIZE); //header长度 - buffer.putLong(this.serviceid); - buffer.putLong(this.nameid); - buffer.putLong(actionid.getFirst()); - buffer.putLong(actionid.getSecond()); - buffer.put(addrBytes[0]); - buffer.put(addrBytes[1]); - buffer.put(addrBytes[2]); - buffer.put(addrBytes[3]); - buffer.putChar((char) this.addrPort); - buffer.putInt(bodyLength); //body长度 - buffer.putInt(bodyOffset); - buffer.putInt(frameLength); //一帧数据的长度 - buffer.putInt(0); //结果码, 请求方固定传0 - buffer.position(currentpos); - } -} diff --git a/src/com/wentch/redkale/net/sncp/SncpDyn.java b/src/com/wentch/redkale/net/sncp/SncpDyn.java deleted file mode 100644 index 4218bdd0a..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpDyn.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * 修饰由SNCP协议动态生成的class、和method - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({METHOD, TYPE}) -@Retention(RUNTIME) -public @interface SncpDyn { - - int index() default 0; //排列顺序, 一般用于Method -} diff --git a/src/com/wentch/redkale/net/sncp/SncpDynServlet.java b/src/com/wentch/redkale/net/sncp/SncpDynServlet.java deleted file mode 100644 index 4aa8aeaf9..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpDynServlet.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import com.wentch.redkale.convert.bson.*; -import static com.wentch.redkale.net.sncp.SncpRequest.DEFAULT_HEADER; -import com.wentch.redkale.service.*; -import com.wentch.redkale.util.*; -import java.io.*; -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.nio.*; -import java.util.*; -import java.util.function.*; -import java.util.logging.*; -import javax.annotation.*; -import jdk.internal.org.objectweb.asm.*; -import static jdk.internal.org.objectweb.asm.Opcodes.*; -import jdk.internal.org.objectweb.asm.Type; - -/** - * - * @author zhangjx - */ -public final class SncpDynServlet extends SncpServlet { - - private static final Logger logger = Logger.getLogger(SncpDynServlet.class.getSimpleName()); - - private final boolean finest = logger.isLoggable(Level.FINEST); - - private final Class type; - - private final String serviceName; - - private final long nameid; - - private final long serviceid; - - private final HashMap actions = new HashMap<>(); - - private Supplier bufferSupplier; - - public SncpDynServlet(final BsonConvert convert, final String serviceName, final Service service, final AnyValue conf) { - this.conf = conf; - this.serviceName = serviceName; - this.type = (Class) service.getClass().getSuperclass(); - this.nameid = Sncp.hash(serviceName); - this.serviceid = Sncp.hash(type); - Set actionids = new HashSet<>(); - for (java.lang.reflect.Method method : service.getClass().getMethods()) { - if (method.isSynthetic()) continue; - if (Modifier.isStatic(method.getModifiers())) continue; - if (Modifier.isFinal(method.getModifiers())) continue; - if (method.getName().equals("getClass") || method.getName().equals("toString")) continue; - if (method.getName().equals("equals") || method.getName().equals("hashCode")) continue; - if (method.getName().equals("notify") || method.getName().equals("notifyAll") || method.getName().equals("wait")) continue; - if (method.getName().equals("init") || method.getName().equals("destroy") || method.getName().equals("name")) continue; - final DLong actionid = Sncp.hash(method); - SncpServletAction action = SncpServletAction.create(service, actionid, method); - action.convert = convert; - if (actionids.contains(actionid)) { - throw new RuntimeException(type.getName() + " have action(Method=" + method + ", actionid=" + actionid + ") same to (" + actions.get(actionid).method + ")"); - } - actions.put(actionid, action); - actionids.add(actionid); - } - } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "(type=" + type.getName() + ", serviceid=" + serviceid + ", actions.size=" + actions.size() + ", name=" + serviceName + ")"; - } - - @Override - public long getNameid() { - return nameid; - } - - @Override - public long getServiceid() { - return serviceid; - } - - @Override - public void execute(SncpRequest request, SncpResponse response) throws IOException { - if (bufferSupplier == null) { - bufferSupplier = request.getContext().getBufferSupplier(); - } - SncpServletAction action = actions.get(request.getActionid()); - //if (finest) logger.log(Level.FINEST, "sncpdyn.execute: " + request + ", " + (action == null ? "null" : action.method)); - if (action == null) { - response.finish(SncpResponse.RETCODE_ILLACTIONID, null); //无效actionid - } else { - BsonWriter out = action.convert.pollBsonWriter(bufferSupplier); - out.writeTo(DEFAULT_HEADER); - BsonReader in = action.convert.pollBsonReader(); - try { - in.setBytes(request.getBody()); - action.action(in, out); - response.finish(0, out); - } catch (Throwable t) { - response.getContext().getLogger().log(Level.INFO, "sncp execute error(" + request + ")", t); - response.finish(SncpResponse.RETCODE_THROWEXCEPTION, null); - } finally { - action.convert.offerBsonReader(in); - action.convert.offerBsonWriter(out); - } - } - } - - public static abstract class SncpServletAction { - - public Method method; - - @Resource - protected BsonConvert convert; - - protected com.wentch.redkale.util.Attribute[] paramAttrs; // 为null表示无SncpCall处理,index=0固定为null, 其他为参数标记的SncpCall回调方法 - - protected java.lang.reflect.Type[] paramTypes; //index=0表示返回参数的type, void的返回参数类型为null - - public abstract void action(final BsonReader in, final BsonWriter out) throws Throwable; - - public final void callParameter(final BsonWriter out, final Object... params) { - if (paramAttrs != null) { - for (int i = 1; i < paramAttrs.length; i++) { - com.wentch.redkale.util.Attribute attr = paramAttrs[i]; - if (attr == null) continue; - out.writeByte((byte) i); - convert.convertTo(out, attr.type(), attr.get(params[i - 1])); - } - } - out.writeByte((byte) 0); - } - - /** ** - * - * public class TestService implements Service { - * public boolean change(TestBean bean, String name, int id) { - * - * } - * } - * - * public class DynActionTestService_change extends SncpServletAction { - * - * public TestService service; - * - * @Override - * public void action(final BsonReader in, final BsonWriter out) throws Throwable { - * TestBean arg1 = convert.convertFrom(in, paramTypes[1]); - * String arg2 = convert.convertFrom(in, paramTypes[2]); - * int arg3 = convert.convertFrom(in, paramTypes[3]); - * Object rs = service.change(arg1, arg2, arg3); - * callParameter(out, arg1, arg2, arg3); - * convert.convertTo(out, paramTypes[0], rs); - * } - * } - */ - /** - * - * @param service - * @param actionid - * @param method - * @return - */ - @SuppressWarnings("unchecked") - public static SncpServletAction create(final Service service, final DLong actionid, final Method method) { - final Class serviceClass = service.getClass(); - final String supDynName = SncpServletAction.class.getName().replace('.', '/'); - final String serviceName = serviceClass.getName().replace('.', '/'); - final String convertName = BsonConvert.class.getName().replace('.', '/'); - final String convertReaderDesc = Type.getDescriptor(BsonReader.class); - final String convertWriterDesc = Type.getDescriptor(BsonWriter.class); - final String serviceDesc = Type.getDescriptor(serviceClass); - String newDynName = serviceName.substring(0, serviceName.lastIndexOf('/') + 1) - + "DynAction" + serviceClass.getSimpleName() + "_" + method.getName() + "_" + actionid; - while (true) { - try { - Class.forName(newDynName.replace('/', '.')); - newDynName += "_"; - } catch (Exception ex) { - break; - } - } - //------------------------------------------------------------- - ClassWriter cw = new ClassWriter(0); - FieldVisitor fv; - DebugMethodVisitor mv; - - cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, supDynName, null); - - { - { - fv = cw.visitField(ACC_PUBLIC, "service", serviceDesc, null, null); - fv.visitEnd(); - } - fv.visitEnd(); - } - { // constructor方法 - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC, "", "()V", null, null)); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, supDynName, "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - String convertFromDesc = "(" + convertReaderDesc + "Ljava/lang/reflect/Type;)Ljava/lang/Object;"; - try { - convertFromDesc = Type.getMethodDescriptor(BsonConvert.class.getMethod("convertFrom", BsonReader.class, java.lang.reflect.Type.class)); - } catch (Exception ex) { - throw new RuntimeException(ex); //不可能会发生 - } - { // action方法 - mv = new DebugMethodVisitor(cw.visitMethod(ACC_PUBLIC, "action", "(" + convertReaderDesc + convertWriterDesc + ")V", null, new String[]{"java/lang/Throwable"})); - //mv.setDebug(true); - int iconst = ICONST_1; - int intconst = 1; - int store = 3; //action的参数个数+1 - final Class[] paramClasses = method.getParameterTypes(); - int[][] codes = new int[paramClasses.length][2]; - for (int i = 0; i < paramClasses.length; i++) { //参数 - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "convert", Type.getDescriptor(BsonConvert.class)); - mv.visitVarInsn(ALOAD, 1); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "paramTypes", "[Ljava/lang/reflect/Type;"); - if (iconst > ICONST_5) { - mv.visitIntInsn(BIPUSH, intconst); - } else { - mv.visitInsn(iconst); // - } - mv.visitInsn(AALOAD); - - mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertFrom", convertFromDesc, false); - int load = ALOAD; - int v = 0; - if (paramClasses[i].isPrimitive()) { - int storecode = ISTORE; - load = ILOAD; - if (paramClasses[i] == long.class) { - storecode = LSTORE; - load = LLOAD; - v = 1; - } else if (paramClasses[i] == float.class) { - storecode = FSTORE; - load = FLOAD; - v = 1; - } else if (paramClasses[i] == double.class) { - storecode = DSTORE; - load = DLOAD; - v = 1; - } - Class bigPrimitiveClass = Array.get(Array.newInstance(paramClasses[i], 1), 0).getClass(); - String bigPrimitiveName = bigPrimitiveClass.getName().replace('.', '/'); - try { - Method pm = bigPrimitiveClass.getMethod(paramClasses[i].getSimpleName() + "Value"); - mv.visitTypeInsn(CHECKCAST, bigPrimitiveName); - mv.visitMethodInsn(INVOKEVIRTUAL, bigPrimitiveName, pm.getName(), Type.getMethodDescriptor(pm), false); - } catch (Exception ex) { - throw new RuntimeException(ex); //不可能会发生 - } - mv.visitVarInsn(storecode, store); - } else { - mv.visitTypeInsn(CHECKCAST, paramClasses[i].getName().replace('.', '/')); - mv.visitVarInsn(ASTORE, store); // - } - codes[i] = new int[]{load, store}; - store += v; - iconst++; - intconst++; - store++; - } - { //调用service - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "service", serviceDesc); - for (int[] j : codes) { - mv.visitVarInsn(j[0], j[1]); - } - mv.visitMethodInsn(INVOKEVIRTUAL, serviceName, method.getName(), Type.getMethodDescriptor(method), false); - } - - final Class returnClass = method.getReturnType(); - if (returnClass != void.class) { - if (returnClass.isPrimitive()) { - Class bigClass = Array.get(Array.newInstance(returnClass, 1), 0).getClass(); - try { - Method vo = bigClass.getMethod("valueOf", returnClass); - mv.visitMethodInsn(INVOKESTATIC, bigClass.getName().replace('.', '/'), vo.getName(), Type.getMethodDescriptor(vo), false); - } catch (Exception ex) { - throw new RuntimeException(ex); //不可能会发生 - } - } - mv.visitVarInsn(ASTORE, store); //11 - } - //------------------------- callParameter 方法 -------------------------------- - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 2); - if (paramClasses.length <= 5) { //参数总数量 - mv.visitInsn(ICONST_0 + paramClasses.length); - } else { - mv.visitIntInsn(BIPUSH, paramClasses.length); - } - mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); - int insn = 2; - for (int j = 0; j < paramClasses.length; j++) { - final Class pt = paramClasses[j]; - mv.visitInsn(DUP); - insn++; - if (j <= 5) { - mv.visitInsn(ICONST_0 + j); - } else { - mv.visitIntInsn(BIPUSH, j); - } - if (pt.isPrimitive()) { - if (pt == long.class) { - mv.visitVarInsn(LLOAD, insn++); - } else if (pt == float.class) { - mv.visitVarInsn(FLOAD, insn++); - } else if (pt == double.class) { - mv.visitVarInsn(DLOAD, insn++); - } else { - mv.visitVarInsn(ILOAD, insn); - } - Class bigclaz = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(pt, 1), 0).getClass(); - mv.visitMethodInsn(INVOKESTATIC, bigclaz.getName().replace('.', '/'), "valueOf", "(" + Type.getDescriptor(pt) + ")" + Type.getDescriptor(bigclaz), false); - } else { - mv.visitVarInsn(ALOAD, insn); - } - mv.visitInsn(AASTORE); - } - mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "callParameter", "(" + convertWriterDesc + "[Ljava/lang/Object;)V", false); - - //-------------------------直接返回 或者 调用convertTo方法 -------------------------------- - int maxStack = codes.length > 0 ? codes[codes.length - 1][1] : 1; - if (returnClass == void.class) { //返回 - mv.visitInsn(RETURN); - maxStack = 8; - } else { - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "convert", Type.getDescriptor(BsonConvert.class)); - mv.visitVarInsn(ALOAD, 2); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, newDynName, "paramTypes", "[Ljava/lang/reflect/Type;"); - mv.visitInsn(ICONST_0); - mv.visitInsn(AALOAD); - mv.visitVarInsn(ALOAD, store); - mv.visitMethodInsn(INVOKEVIRTUAL, convertName, "convertTo", "(" + convertWriterDesc + "Ljava/lang/reflect/Type;Ljava/lang/Object;)V", false); - mv.visitInsn(RETURN); - store++; - if (maxStack < 10) maxStack = 10; - } - mv.visitMaxs(maxStack, store); - mv.visitEnd(); - } - cw.visitEnd(); - - byte[] bytes = cw.toByteArray(); - Class newClazz = new ClassLoader(serviceClass.getClassLoader()) { - public final Class loadClass(String name, byte[] b) { - return defineClass(name, b, 0, b.length); - } - }.loadClass(newDynName.replace('/', '.'), bytes); - try { - SncpServletAction instance = (SncpServletAction) newClazz.newInstance(); - instance.method = method; - java.lang.reflect.Type[] ptypes = method.getGenericParameterTypes(); - java.lang.reflect.Type[] types = new java.lang.reflect.Type[ptypes.length + 1]; - java.lang.reflect.Type rt = method.getGenericReturnType(); - if (rt instanceof TypeVariable) { - TypeVariable tv = (TypeVariable) rt; - if (tv.getBounds().length == 1) rt = tv.getBounds()[0]; - } - types[0] = rt; - System.arraycopy(ptypes, 0, types, 1, ptypes.length); - instance.paramTypes = types; - - com.wentch.redkale.util.Attribute[] atts = new com.wentch.redkale.util.Attribute[ptypes.length + 1]; - Annotation[][] anns = method.getParameterAnnotations(); - boolean hasattr = false; - for (int i = 0; i < anns.length; i++) { - if (anns[i].length > 0) { - for (Annotation ann : anns[i]) { - if (ann.annotationType() == SncpCall.class) { - try { - atts[i + 1] = ((SncpCall) ann).value().newInstance(); - hasattr = true; - } catch (Exception e) { - logger.log(Level.SEVERE, SncpCall.class.getSimpleName() + ".attribute cannot a newInstance for" + method, e); - } - break; - } - } - } - } - if (hasattr) instance.paramAttrs = atts; - newClazz.getField("service").set(instance, service); - return instance; - } catch (Exception ex) { - throw new RuntimeException(ex); //不可能会发生 - } - } - } - -} diff --git a/src/com/wentch/redkale/net/sncp/SncpFuture.java b/src/com/wentch/redkale/net/sncp/SncpFuture.java deleted file mode 100644 index 68cf07b8a..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpFuture.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import java.util.concurrent.*; - -/** - * 简单的Future实现, set、get方法均只能一个线程调用 - * - * @author zhangjx - * @param - */ -public class SncpFuture implements Future { - - private volatile boolean done; - - private T result; - - private RuntimeException ex; - - public SncpFuture() { - } - - public SncpFuture(T result) { - this.result = result; - this.done = true; - } - - public void set(T result) { - this.result = result; - this.done = true; - synchronized (this) { - notifyAll(); - } - } - - public void set(RuntimeException ex) { - this.ex = ex; - this.done = true; - synchronized (this) { - notifyAll(); - } - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - return false; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return done; - } - - @Override - public T get() throws InterruptedException, ExecutionException { - if (done) { - if (ex != null) throw ex; - return result; - } - synchronized (this) { - if (!done) wait(10_000); - } - if (done) { - if (ex != null) throw ex; - return result; - } - throw new InterruptedException(); - } - - @Override - public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - if (done) { - if (ex != null) throw ex; - return result; - } - synchronized (this) { - if (!done) wait(unit.toMillis(timeout)); - } - if (done) { - if (ex != null) throw ex; - return result; - } - throw new TimeoutException(); - } -} diff --git a/src/com/wentch/redkale/net/sncp/SncpPrepareServlet.java b/src/com/wentch/redkale/net/sncp/SncpPrepareServlet.java deleted file mode 100644 index f14c2640b..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpPrepareServlet.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import com.wentch.redkale.net.PrepareServlet; -import com.wentch.redkale.net.Context; -import com.wentch.redkale.util.AnyValue; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.*; - -/** - * - * @author zhangjx - */ -public class SncpPrepareServlet extends PrepareServlet { - - private static final ByteBuffer pongBuffer = ByteBuffer.wrap("PONG".getBytes()).asReadOnlyBuffer(); - - private final Map> maps = new HashMap<>(); - - private final Map singlemaps = new HashMap<>(); - - public void addSncpServlet(SncpServlet servlet) { - if (servlet.getNameid() == 0) { - synchronized (singlemaps) { - singlemaps.put(servlet.getServiceid(), servlet); - } - } else { - synchronized (maps) { - Map m = maps.get(servlet.getServiceid()); - if (m == null) { - m = new HashMap<>(); - maps.put(servlet.getServiceid(), m); - } - m.put(servlet.getNameid(), servlet); - } - } - } - - public List getSncpServlets() { - ArrayList list = new ArrayList<>(singlemaps.values()); - maps.values().forEach(x -> list.addAll(x.values())); - return list; - } - - @Override - public void init(Context context, AnyValue config) { - Collection> values = this.maps.values(); - values.stream().forEach((en) -> { - en.values().stream().forEach(s -> s.init(context, s.conf)); - }); - } - - @Override - public void destroy(Context context, AnyValue config) { - Collection> values = this.maps.values(); - values.stream().forEach((en) -> { - en.values().stream().forEach(s -> s.destroy(context, s.conf)); - }); - } - - @Override - public void execute(SncpRequest request, SncpResponse response) throws IOException { - if (request.isPing()) { - response.finish(pongBuffer.duplicate()); - return; - } - SncpServlet servlet; - if (request.getNameid() == 0) { - servlet = singlemaps.get(request.getServiceid()); - if (servlet == null) { - response.finish(SncpResponse.RETCODE_ILLSERVICEID, null); //无效serviceid - return; - } - } else { - Map m = maps.get(request.getServiceid()); - if (m == null) { - response.finish(SncpResponse.RETCODE_ILLSERVICEID, null); //无效serviceid - return; - } - servlet = m.get(request.getNameid()); - } - if (servlet == null) { - response.finish(SncpResponse.RETCODE_ILLNAMEID, null); //无效nameid - } else { - servlet.execute(request, response); - } - } - -} diff --git a/src/com/wentch/redkale/net/sncp/SncpRemote.java b/src/com/wentch/redkale/net/sncp/SncpRemote.java deleted file mode 100644 index 200a73523..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpRemote.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * 用于在 Service 中创建自身远程模式的对象 - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({FIELD}) -@Retention(RUNTIME) -public @interface SncpRemote { - -} diff --git a/src/com/wentch/redkale/net/sncp/SncpRequest.java b/src/com/wentch/redkale/net/sncp/SncpRequest.java deleted file mode 100644 index 34a9342f1..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpRequest.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import com.wentch.redkale.convert.bson.*; -import com.wentch.redkale.net.*; -import com.wentch.redkale.util.*; -import java.net.*; -import java.nio.*; - -/** - * - * @author zhangjx - */ -public final class SncpRequest extends Request { - - public static final int HEADER_SIZE = 64; - - public static final byte[] DEFAULT_HEADER = new byte[HEADER_SIZE]; - - protected final BsonConvert convert; - - private long seqid; - - private long nameid; - - private long serviceid; - - private DLong actionid; - - private int bodylength; - - private int bodyoffset; - - private int framelength; - - private boolean ping; - - private byte[] body; - - private byte[] bufferbytes = new byte[6]; - - protected SncpRequest(Context context) { - super(context); - this.convert = context.getBsonConvert(); - } - - @Override - protected int readHeader(ByteBuffer buffer) { - if (buffer.remaining() < HEADER_SIZE) { - this.ping = true; - return 0; - } - //---------------------head---------------------------------- - this.seqid = buffer.getLong(); - if (buffer.getChar() != HEADER_SIZE) { - context.getLogger().finest("sncp buffer header.length not " + HEADER_SIZE); - return -1; - } - this.serviceid = buffer.getLong(); - this.nameid = buffer.getLong(); - this.actionid = new DLong(buffer.getLong(), buffer.getLong()); - buffer.get(bufferbytes); - this.bodylength = buffer.getInt(); - this.bodyoffset = buffer.getInt(); - this.framelength = buffer.getInt(); - - if (buffer.getInt() != 0) { - context.getLogger().finest("sncp buffer header.retcode not 0"); - return -1; - } - //---------------------body---------------------------------- - this.body = new byte[this.bodylength]; - int len = Math.min(this.bodylength, buffer.remaining()); - buffer.get(body, 0, len); - this.bodyoffset = len; - return bodylength - len; - } - - @Override - protected int readBody(ByteBuffer buffer) { - final int framelen = buffer.remaining(); - buffer.get(this.body, this.bodyoffset, framelen); - this.bodyoffset += framelen; - return framelen; - } - - @Override - protected void prepare() { - this.keepAlive = true; - } - - @Override - public String toString() { - return SncpRequest.class.getSimpleName() + "{seqid=" + this.seqid - + ",serviceid=" + this.serviceid + ",actionid=" + this.actionid - + ",bodylength=" + this.bodylength + ",bodyoffset=" + this.bodyoffset - + ",framelength=" + this.framelength + ",remoteAddress=" + getRemoteAddress() + "}"; - } - - @Override - protected void recycle() { - this.seqid = 0; - this.framelength = 0; - this.serviceid = 0; - this.actionid = null; - this.bodylength = 0; - this.bodyoffset = 0; - this.body = null; - this.ping = false; - this.bufferbytes[0] = 0; - super.recycle(); - } - - protected boolean isPing() { - return ping; - } - - public byte[] getBody() { - return body; - } - - public long getSeqid() { - return seqid; - } - - public long getServiceid() { - return serviceid; - } - - public long getNameid() { - return nameid; - } - - public DLong getActionid() { - return actionid; - } - - public InetSocketAddress getRemoteAddress() { - if (bufferbytes[0] == 0) return null; - return new InetSocketAddress((0xff & bufferbytes[0]) + "." + (0xff & bufferbytes[1]) + "." + (0xff & bufferbytes[2]) + "." + (0xff & bufferbytes[3]), - ((0xff00 & (bufferbytes[4] << 8)) | (0xff & bufferbytes[5]))); - } - -} diff --git a/src/com/wentch/redkale/net/sncp/SncpResponse.java b/src/com/wentch/redkale/net/sncp/SncpResponse.java deleted file mode 100644 index 22f5e4c55..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpResponse.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import com.wentch.redkale.convert.bson.*; -import com.wentch.redkale.net.*; -import static com.wentch.redkale.net.sncp.SncpRequest.HEADER_SIZE; -import com.wentch.redkale.util.*; -import java.nio.*; -import java.util.concurrent.atomic.*; - -/** - * - * @author zhangjx - */ -public final class SncpResponse extends Response { - - public static final int RETCODE_ILLSERVICEID = 10001; //无效serviceid - - public static final int RETCODE_ILLNAMEID = 10002; //无效nameid - - public static final int RETCODE_ILLACTIONID = 10003; //无效actionid - - public static final int RETCODE_THROWEXCEPTION = 10011; //内部异常 - - public static ObjectPool createPool(AtomicLong creatCounter, AtomicLong cycleCounter, int max, Creator creator) { - return new ObjectPool<>(creatCounter, cycleCounter, max, creator, (x) -> ((SncpResponse) x).prepare(), (x) -> ((SncpResponse) x).recycle()); - } - - private final byte[] addrBytes; - - private final int addrPort; - - public static String getRetCodeInfo(int retcode) { - if (retcode == RETCODE_ILLSERVICEID) return "serviceid is invalid"; - if (retcode == RETCODE_ILLNAMEID) return "nameid is invalid"; - if (retcode == RETCODE_ILLACTIONID) return "actionid is invalid"; - if (retcode == RETCODE_THROWEXCEPTION) return "Inner exception"; - return null; - } - - protected SncpResponse(Context context, SncpRequest request) { - super(context, request); - this.addrBytes = context.getServerAddress().getAddress().getAddress(); - this.addrPort = context.getServerAddress().getPort(); - } - - public void finish(final int retcode, final BsonWriter out) { - if (out == null) { - final ByteBuffer buffer = context.pollBuffer(); - fillHeader(buffer, 0, 0, 0, retcode); - finish(buffer); - return; - } - final int respBodyLength = out.count(); //body总长度 - final ByteBuffer[] buffers = out.toBuffers(); - fillHeader(buffers[0], respBodyLength - HEADER_SIZE, 0, respBodyLength - HEADER_SIZE, retcode); - finish(buffers); - } - - private void fillHeader(ByteBuffer buffer, int bodyLength, int bodyOffset, int framelength, int retcode) { - //---------------------head---------------------------------- - final int currentpos = buffer.position(); - buffer.position(0); - buffer.putLong(request.getSeqid()); - buffer.putChar((char) SncpRequest.HEADER_SIZE); - buffer.putLong(request.getServiceid()); - buffer.putLong(request.getNameid()); - DLong actionid = request.getActionid(); - buffer.putLong(actionid.getFirst()); - buffer.putLong(actionid.getSecond()); - buffer.put(addrBytes); - buffer.putChar((char) this.addrPort); - buffer.putInt(bodyLength); - buffer.putInt(bodyOffset); - buffer.putInt(framelength); - buffer.putInt(retcode); - buffer.position(currentpos); - } -} diff --git a/src/com/wentch/redkale/net/sncp/SncpServer.java b/src/com/wentch/redkale/net/sncp/SncpServer.java deleted file mode 100644 index 4c464351f..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpServer.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import com.wentch.redkale.convert.bson.*; -import com.wentch.redkale.net.*; -import com.wentch.redkale.util.*; -import com.wentch.redkale.watch.*; -import java.nio.*; -import java.util.*; -import java.util.concurrent.atomic.*; - -/** - * Service Node Communicate Protocol - * - * @author zhangjx - */ -public final class SncpServer extends Server { - - public SncpServer() { - this(System.currentTimeMillis(), null); - } - - public SncpServer(long serverStartTime, final WatchFactory watch) { - super(serverStartTime, "TCP", new SncpPrepareServlet(), watch); - } - - @Override - public void init(AnyValue config) throws Exception { - super.init(config); - } - - public void addService(ServiceWrapper entry) { - ((SncpPrepareServlet) this.prepare).addSncpServlet(new SncpDynServlet(BsonFactory.root().getConvert(), entry.getName(), entry.getService(), entry.getConf())); - } - - public List getSncpServlets() { - return ((SncpPrepareServlet) this.prepare).getSncpServlets(); - } - - @Override - @SuppressWarnings("unchecked") - protected Context createContext() { - final int port = this.address.getPort(); - AtomicLong createBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Buffer.creatCounter"); - AtomicLong cycleBufferCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Buffer.cycleCounter"); - final int rcapacity = Math.max(this.capacity, 4 * 1024); - ObjectPool bufferPool = new ObjectPool<>(createBufferCounter, cycleBufferCounter, this.bufferPoolSize, - (Object... params) -> ByteBuffer.allocateDirect(rcapacity), null, (e) -> { - if (e == null || e.isReadOnly() || e.capacity() != rcapacity) return false; - e.clear(); - return true; - }); - AtomicLong createResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Response.creatCounter"); - AtomicLong cycleResponseCounter = watch == null ? new AtomicLong() : watch.createWatchNumber("SNCP_" + port + ".Response.cycleCounter"); - ObjectPool responsePool = SncpResponse.createPool(createResponseCounter, cycleResponseCounter, this.responsePoolSize, null); - Context sncpcontext = new Context(this.serverStartTime, this.logger, executor, rcapacity, bufferPool, responsePool, - this.maxbody, this.charset, this.address, this.prepare, this.watch, this.readTimeoutSecond, this.writeTimeoutSecond); - responsePool.setCreator((Object... params) -> new SncpResponse(sncpcontext, new SncpRequest(sncpcontext))); - return sncpcontext; - } - -} diff --git a/src/com/wentch/redkale/net/sncp/SncpServlet.java b/src/com/wentch/redkale/net/sncp/SncpServlet.java deleted file mode 100644 index c079a06ad..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpServlet.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import com.wentch.redkale.net.Servlet; -import com.wentch.redkale.util.AnyValue; - -/** - * - * @author zhangjx - */ -public abstract class SncpServlet implements Servlet { - - AnyValue conf; - - public abstract long getNameid(); - - public abstract long getServiceid(); - - @Override - public final boolean equals(Object obj) { - return obj != null && obj.getClass() == this.getClass(); - } - - @Override - public final int hashCode() { - return this.getClass().hashCode(); - } -} diff --git a/src/com/wentch/redkale/net/sncp/SncpTargetAddress.java b/src/com/wentch/redkale/net/sncp/SncpTargetAddress.java deleted file mode 100644 index f966ec205..000000000 --- a/src/com/wentch/redkale/net/sncp/SncpTargetAddress.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.net.sncp; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * SNCP协议中标记为目标地址参数, 该注解只能标记在类型为SocketAddress或其之类的参数上。 - * - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({PARAMETER}) -@Retention(RUNTIME) -public @interface SncpTargetAddress { - -} diff --git a/src/com/wentch/redkale/service/DataCacheListenerService.java b/src/com/wentch/redkale/service/DataCacheListenerService.java deleted file mode 100644 index 4fdd375ad..000000000 --- a/src/com/wentch/redkale/service/DataCacheListenerService.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.service; - -import com.wentch.redkale.source.*; -import com.wentch.redkale.util.*; -import java.io.*; -import javax.annotation.*; - -/** - * - * @author zhangjx - */ -@AutoLoad(false) -public class DataCacheListenerService implements DataCacheListener, Service { - - @Resource(name = "$") - private DataSource source; - - @Override - @MultiRun(selfrun = false, async = true) - public void insertCache(Class clazz, T... entitys) { - ((DataDefaultSource) source).insertCache(clazz, entitys); - } - - @Override - @MultiRun(selfrun = false, async = true) - public void updateCache(Class clazz, T... entitys) { - ((DataDefaultSource) source).updateCache(clazz, entitys); - } - - @Override - @MultiRun(selfrun = false, async = true) - public void deleteCache(Class clazz, Serializable... ids) { - ((DataDefaultSource) source).deleteCache(clazz, ids); - } - -} diff --git a/src/com/wentch/redkale/service/DataSQLListenerService.java b/src/com/wentch/redkale/service/DataSQLListenerService.java deleted file mode 100644 index 1b1961fa0..000000000 --- a/src/com/wentch/redkale/service/DataSQLListenerService.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.service; - -import com.wentch.redkale.source.DataSQLListener; -import com.wentch.redkale.source.DataSource; -import com.wentch.redkale.source.DataDefaultSource; -import com.wentch.redkale.util.AnyValue; -import com.wentch.redkale.util.AutoLoad; -import java.io.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.logging.*; -import javax.annotation.Resource; - -/** - * 暂时不实现 - * - * @author zhangjx - */ -@AutoLoad(false) -public class DataSQLListenerService implements DataSQLListener, Service { - - private static final String format = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL"; - - protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName()); - - private final boolean finest = logger.isLoggable(Level.FINEST); - - @Resource(name = "APP_HOME") - private File home; - - @Resource(name = "$") - private DataSource source; - - private final BlockingQueue queue = new ArrayBlockingQueue<>(1024 * 1024); - - private PrintStream syncfile; - - @Override - public void init(AnyValue config) { - new Thread() { - { - setName(DataSQLListener.class.getSimpleName() + "-Thread"); - setDaemon(true); - } - - @Override - public void run() { - while (true) { - try { - String sql = queue.take(); - send(sql); - } catch (Exception e) { - logger.log(Level.SEVERE, this.getName() + " occur error"); - } - } - } - }.start(); - - } - - @Override - public void destroy(AnyValue config) { - if (syncfile != null) syncfile.close(); - } - - private void write(String... sqls) { - try { - if (syncfile == null) { - File root = new File(home, "dbsync"); - root.mkdirs(); - syncfile = new PrintStream(new FileOutputStream(new File(root, "sql-" + name() + ".sql"), true), false, "UTF-8"); - } - for (String sql : sqls) { - syncfile.print(sql + ";\r\n"); - } - syncfile.flush(); - } catch (Exception e) { - logger.log(Level.WARNING, "write sql file error. (" + name() + ", " + Arrays.toString(sqls) + ")", e); - } - } - - @Override - public void insert(String... sqls) { - put(sqls); - } - - @Override - public void update(String... sqls) { - put(sqls); - } - - @Override - public void delete(String... sqls) { - put(sqls); - } - - private void put(String... sqls) { - String date = String.format(format, System.currentTimeMillis()); - for (String sql : sqls) { - try { - queue.put("/* " + date + " */ " + sql); - } catch (Exception e) { - write(sql); - } - } - } - - @MultiRun - public void send(String... sqls) { - ((DataDefaultSource) source).execute(sqls); - } - -} diff --git a/src/com/wentch/redkale/service/DataSourceService.java b/src/com/wentch/redkale/service/DataSourceService.java deleted file mode 100644 index e92616ceb..000000000 --- a/src/com/wentch/redkale/service/DataSourceService.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.service; - -import com.wentch.redkale.net.sncp.*; -import com.wentch.redkale.source.*; -import com.wentch.redkale.util.*; -import java.io.*; -import java.util.*; -import javax.annotation.*; - -/** - * DataSource对应的Service类, 该类主要特点是将所有含FilterBean参数的方法重载成FilterNode对应的方法。 - * - * @author zhangjx - */ -@AutoLoad(false) -public class DataSourceService implements DataSource, Service { - - @Resource(name = "$") - private DataSource source; - - @Override - public DataConnection createReadConnection() { - return source.createReadConnection(); - } - - @Override - public DataConnection createWriteConnection() { - return source.createWriteConnection(); - } - - @Override - public void insert(@SncpCall(DataCallArrayAttribute.class) T... values) { - source.insert(values); - } - - @Override - public void insert(DataConnection conn, @SncpCall(DataCallArrayAttribute.class) T... values) { - source.insert(conn, values); - } - - @Override - public void refreshCache(Class clazz) { - source.refreshCache(clazz); - } - - @Override - public void delete(T... values) { - source.delete(values); - } - - @Override - public void delete(DataConnection conn, T... values) { - source.delete(conn, values); - } - - @Override - public void delete(Class clazz, Serializable... ids) { - source.delete(clazz, ids); - } - - @Override - public void delete(DataConnection conn, Class clazz, Serializable... ids) { - source.delete(conn, clazz, ids); - } - - @Override - public void delete(Class clazz, FilterNode node) { - source.delete(clazz, node); - } - - @Override - public void delete(DataConnection conn, Class clazz, FilterNode node) { - source.delete(conn, clazz, node); - } - - @Override - public void update(T... values) { - source.update(values); - } - - @Override - public void update(DataConnection conn, T... values) { - source.update(conn, values); - } - - @Override - public void updateColumn(Class clazz, Serializable id, String column, Serializable value) { - source.updateColumn(clazz, id, column, value); - } - - @Override - public void updateColumn(DataConnection conn, Class clazz, Serializable id, String column, Serializable value) { - source.updateColumn(conn, clazz, id, column, value); - } - - @Override - public void updateColumns(T value, String... columns) { - source.updateColumns(value, columns); - } - - @Override - public void updateColumns(DataConnection conn, T value, String... columns) { - source.updateColumns(conn, value, columns); - } - - @Override - public void updateColumnIncrement(Class clazz, Serializable id, String column, long incvalue) { - source.updateColumnIncrement(clazz, id, column, incvalue); - } - - @Override - public void updateColumnIncrement(DataConnection conn, Class clazz, Serializable id, String column, long incvalue) { - source.updateColumnIncrement(conn, clazz, id, column, incvalue); - } - - @Override - public void updateColumnAnd(Class clazz, Serializable id, String column, long incvalue) { - source.updateColumnAnd(clazz, id, column, incvalue); - } - - @Override - public void updateColumnAnd(DataConnection conn, Class clazz, Serializable id, String column, long incvalue) { - source.updateColumnAnd(conn, clazz, id, column, incvalue); - } - - @Override - public void updateColumnOr(Class clazz, Serializable id, String column, long incvalue) { - source.updateColumnOr(clazz, id, column, incvalue); - } - - @Override - public void updateColumnOr(DataConnection conn, Class clazz, Serializable id, String column, long incvalue) { - source.updateColumnOr(conn, clazz, id, column, incvalue); - } - - @Override - public Number getNumberResult(Class entityClass, Reckon reckon, String column) { - return source.getNumberResult(entityClass, reckon, column); - } - - @Override - public final Number getNumberResult(Class entityClass, Reckon reckon, String column, FilterBean bean) { - return getNumberResult(entityClass, reckon, column, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public Number getNumberResult(Class entityClass, Reckon reckon, String column, FilterNode node) { - return source.getNumberResult(entityClass, reckon, column, node); - } - - @Override - public Map getMapResult(Class entityClass, String keyColumn, Reckon reckon, String reckonColumn) { - return source.getMapResult(entityClass, keyColumn, reckon, reckonColumn); - } - - @Override - public final Map getMapResult(Class entityClass, String keyColumn, Reckon reckon, String reckonColumn, FilterBean bean) { - return getMapResult(entityClass, keyColumn, reckon, reckonColumn, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public Map getMapResult(Class entityClass, String keyColumn, Reckon reckon, String reckonColumn, FilterNode node) { - return source.getMapResult(entityClass, keyColumn, reckon, reckonColumn, node); - } - - @Override - public T find(Class clazz, Serializable pk) { - return source.find(clazz, pk); - } - - @Override - public T find(Class clazz, SelectColumn selects, Serializable pk) { - return source.find(clazz, selects, pk); - } - - @Override - public T findByColumn(Class clazz, String column, Serializable key) { - return source.findByColumn(clazz, column, key); - } - - @Override - public T find(Class clazz, FilterNode node) { - return source.find(clazz, node); - } - - @Override - public final T find(Class clazz, FilterBean bean) { - return find(clazz, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public boolean exists(Class clazz, Serializable pk) { - return source.exists(clazz, pk); - } - - @Override - public boolean exists(Class clazz, FilterNode node) { - return source.exists(clazz, node); - } - - @Override - public final boolean exists(Class clazz, FilterBean bean) { - return exists(clazz, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public HashSet queryColumnSet(String selectedColumn, Class clazz, String column, Serializable key) { - return source.queryColumnSet(selectedColumn, clazz, column, key); - } - - @Override - public HashSet queryColumnSet(String selectedColumn, Class clazz, FilterNode node) { - return source.queryColumnSet(selectedColumn, clazz, node); - } - - @Override - public final HashSet queryColumnSet(String selectedColumn, Class clazz, FilterBean bean) { - return queryColumnSet(selectedColumn, clazz, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public List queryColumnList(String selectedColumn, Class clazz, String column, Serializable key) { - return source.queryColumnList(selectedColumn, clazz, column, key); - } - - @Override - public List queryColumnList(String selectedColumn, Class clazz, FilterNode node) { - return source.queryColumnList(selectedColumn, clazz, node); - } - - @Override - public final List queryColumnList(String selectedColumn, Class clazz, FilterBean bean) { - return queryColumnList(selectedColumn, clazz, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public Map queryMap(Class clazz, FilterNode node) { - return source.queryMap(clazz, node); - } - - @Override - public final Map queryMap(Class clazz, FilterBean bean) { - return queryMap(clazz, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public Map queryMap(Class clazz, SelectColumn selects, FilterNode node) { - return source.queryMap(clazz, selects, node); - } - - @Override - public final Map queryMap(Class clazz, SelectColumn selects, FilterBean bean) { - return queryMap(clazz, selects, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public List queryList(Class clazz, String column, Serializable key) { - return source.queryList(clazz, column, key); - } - - @Override - public List queryList(Class clazz, FilterNode node) { - return source.queryList(clazz, node); - } - - @Override - public final List queryList(Class clazz, FilterBean bean) { - return queryList(clazz, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public List queryList(Class clazz, SelectColumn selects, FilterNode node) { - return source.queryList(clazz, selects, node); - } - - @Override - public final List queryList(Class clazz, SelectColumn selects, FilterBean bean) { - return queryList(clazz, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public List queryList(Class clazz, Flipper flipper, String column, Serializable key) { - return source.queryList(clazz, flipper, column, key); - } - - @Override - public List queryList(Class clazz, Flipper flipper, FilterNode node) { - return source.queryList(clazz, flipper, node); - } - - @Override - public final List queryList(Class clazz, Flipper flipper, FilterBean bean) { - return queryList(clazz, flipper, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public List queryList(Class clazz, SelectColumn selects, Flipper flipper, FilterNode node) { - return source.queryList(clazz, selects, flipper, node); - } - - @Override - public final List queryList(Class clazz, SelectColumn selects, Flipper flipper, FilterBean bean) { - return queryList(clazz, selects, flipper, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public final Sheet queryColumnSheet(String selectedColumn, Class clazz, Flipper flipper, FilterBean bean) { - return queryColumnSheet(selectedColumn, clazz, flipper, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public Sheet queryColumnSheet(String selectedColumn, Class clazz, Flipper flipper, FilterNode node) { - return source.queryColumnSheet(selectedColumn, clazz, flipper, node); - } - - @Override - public final Sheet querySheet(Class clazz, Flipper flipper, FilterBean bean) { - return querySheet(clazz, flipper, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public Sheet querySheet(Class clazz, Flipper flipper, FilterNode node) { - return source.querySheet(clazz, flipper, node); - } - - @Override - public final Sheet querySheet(Class clazz, SelectColumn selects, Flipper flipper, FilterBean bean) { - return querySheet(clazz, selects, flipper, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public Sheet querySheet(Class clazz, SelectColumn selects, Flipper flipper, FilterNode node) { - return source.querySheet(clazz, selects, flipper, node); - } - -} diff --git a/src/com/wentch/redkale/service/LocalService.java b/src/com/wentch/redkale/service/LocalService.java deleted file mode 100644 index 5cf30d96a..000000000 --- a/src/com/wentch/redkale/service/LocalService.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.service; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * 声明为LocalService的Service将不会变成远程模式, 无论配置文件中是否配置成远程模式。 - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({TYPE}) -@Retention(RUNTIME) -public @interface LocalService { - -} diff --git a/src/com/wentch/redkale/service/MultiRun.java b/src/com/wentch/redkale/service/MultiRun.java deleted file mode 100644 index 93b9b7f8f..000000000 --- a/src/com/wentch/redkale/service/MultiRun.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.service; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * MultiRun 只对本地模式Service有效 - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({METHOD}) -@Retention(RUNTIME) -public @interface MultiRun { - - boolean selfrun() default true; //当前本地实例是否运行指定操作;只有当指定操作的方法的返回值为void时,该值才有效。 - - boolean samerun() default true; //是否同组节点也运行指定操作 - - boolean diffrun() default true; //是否不同组节点也运行指定操作 - - boolean async() default true; //分布式运行是否采用异步模式 -} diff --git a/src/com/wentch/redkale/service/RetResult.java b/src/com/wentch/redkale/service/RetResult.java deleted file mode 100644 index 437dba471..000000000 --- a/src/com/wentch/redkale/service/RetResult.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.service; - -import com.wentch.redkale.convert.json.*; - -/** - * 通用的结果对象,在常见的HTTP+JSON接口中返回的结果需要含结果码,错误信息,和实体对象。 - * - * @author zhangjx - * @param - */ -public class RetResult { - - protected static final class RetSuccessResult extends RetResult { - - public RetSuccessResult() { - } - - @Override - public void setRetcode(int retcode) { - } - - @Override - public void setRetinfo(String retinfo) { - } - - @Override - public void setResult(T result) { - } - } - - public static final RetResult SUCCESS = new RetSuccessResult(); - - protected int retcode; - - protected String retinfo; - - private T result; - - public RetResult() { - } - - public RetResult(T result) { - this.result = result; - } - - public RetResult(int retcode) { - this.retcode = retcode; - } - - public RetResult(int retcode, String retinfo) { - this.retcode = retcode; - this.retinfo = retinfo; - } - - public RetResult(int retcode, String retinfo, T result) { - this.retcode = retcode; - this.retinfo = retinfo; - this.result = result; - } - - /** - * 判断结果是否成功返回, retcode = 0 视为成功, 否则视为错误码 - * - * @return - */ - public boolean isSuccess() { - return retcode == 0; - } - - /** - * 结果码 0表示成功、 非0表示错误 - * - * @return - */ - public int getRetcode() { - return retcode; - } - - public void setRetcode(int retcode) { - this.retcode = retcode; - } - - public String getRetinfo() { - return retinfo; - } - - public void setRetinfo(String retinfo) { - this.retinfo = retinfo; - } - - /** - * 结果对象, 通常只有在retcode = 0时值才有效 - * - * @return - */ - public T getResult() { - return result; - } - - public void setResult(T result) { - this.result = result; - } - - @Override - public String toString() { - return JsonFactory.root().getConvert().convertTo(this); - } -} diff --git a/src/com/wentch/redkale/service/Service.java b/src/com/wentch/redkale/service/Service.java deleted file mode 100644 index 3976817fa..000000000 --- a/src/com/wentch/redkale/service/Service.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.service; - -import com.wentch.redkale.util.*; - -/** - * 所有Service的实现类不得声明为final, 允许远程模式的public方法和public String name()方法都不能声明为final。 - *

- * @Resource(name = ".*") - * private HashMap nodemap; - * 被注入的多个XXXService实例 但不会包含自身的XXXService。 - * - * @author zhangjx - */ -public interface Service extends Nameable { - - /** - * 该方法必须是可以重复调用, 当reload时需要重复调用init方法 - * - * @param config - */ - default void init(AnyValue config) { - - } - - default void destroy(AnyValue config) { - - } - - /** - * Service的name, 一个Service在同一进程内可以包含多个实例, 使用name区分 - *

- * @return - */ - @Override - default String name() { - return ""; - } -} diff --git a/src/com/wentch/redkale/service/WebSocketNodeService.java b/src/com/wentch/redkale/service/WebSocketNodeService.java deleted file mode 100644 index b7e890202..000000000 --- a/src/com/wentch/redkale/service/WebSocketNodeService.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.service; - -import com.wentch.redkale.net.http.*; -import static com.wentch.redkale.net.http.WebSocket.*; -import com.wentch.redkale.net.sncp.*; -import com.wentch.redkale.util.*; -import java.io.*; -import java.net.*; -import java.util.*; - -/** - * - * @author zhangjx - */ -@AutoLoad(false) -public class WebSocketNodeService extends WebSocketNode implements Service { - - @Override - public void init(AnyValue conf) { - super.init(conf); - } - - @Override - public void destroy(AnyValue conf) { - super.destroy(conf); - } - - @Override - public int sendMessage(@SncpTargetAddress InetSocketAddress addr, Serializable groupid, boolean recent, Serializable message, boolean last) { - final Set engineids = localNodes.get(groupid); - if (engineids == null || engineids.isEmpty()) return RETCODE_GROUP_EMPTY; - int code = RETCODE_GROUP_EMPTY; - for (String engineid : engineids) { - final WebSocketEngine engine = engines.get(engineid); - if (engine != null) { //在本地 - final WebSocketGroup group = engine.getWebSocketGroup(groupid); - if (group == null || group.isEmpty()) { - if (finest) logger.finest("receive websocket message {engineid:'" + engineid + "', groupid:" + groupid + ", content:'" + message + "'} but result is " + RETCODE_GROUP_EMPTY); - return RETCODE_GROUP_EMPTY; - } - code = group.send(recent, message, last); - if (finest) logger.finest("websocket node send message (" + message + ") result is " + code); - } - } - return code; - } - - @Override - @MultiRun - public void connect(Serializable groupid, InetSocketAddress addr) { - LinkedHashSet addrs = dataNodes.get(groupid); - if (addrs == null) { - addrs = new LinkedHashSet<>(); - dataNodes.put(groupid, addrs); - } - addrs.add(addr); - if (finest) logger.finest(WebSocketNodeService.class.getSimpleName() + ".event: " + groupid + " connect from " + addr); - } - - @Override - @MultiRun - public void disconnect(Serializable groupid, InetSocketAddress addr) { - Set addrs = dataNodes.get(groupid); - if (addrs == null) return; - synchronized (addrs) { - addrs.remove(addr); - } - if (addrs.isEmpty()) dataNodes.remove(groupid); - if (finest) logger.finest(WebSocketNodeService.class.getSimpleName() + ".event: " + groupid + " disconnect from " + addr); - } -} diff --git a/src/com/wentch/redkale/source/DataCacheListener.java b/src/com/wentch/redkale/source/DataCacheListener.java deleted file mode 100644 index 62daf311a..000000000 --- a/src/com/wentch/redkale/source/DataCacheListener.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import java.io.Serializable; - -/** - * - * @author zhangjx - */ -public interface DataCacheListener { - - public void insertCache(Class clazz, T... entitys); - - public void updateCache(Class clazz, T... entitys); - - public void deleteCache(Class clazz, Serializable... ids); -} diff --git a/src/com/wentch/redkale/source/DataCallArrayAttribute.java b/src/com/wentch/redkale/source/DataCallArrayAttribute.java deleted file mode 100644 index 1b792bac4..000000000 --- a/src/com/wentch/redkale/source/DataCallArrayAttribute.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import com.wentch.redkale.util.*; -import java.io.*; -import java.lang.reflect.*; - -/** - * - * @author zhangjx - * @param - * @param - */ -public final class DataCallArrayAttribute implements Attribute { - - public static final DataCallArrayAttribute instance = new DataCallArrayAttribute(); - - @Override - public Class type() { - return (Class) Object.class; - } - - @Override - public Class declaringClass() { - return (Class) (Class) Object[].class; - } - - @Override - public String field() { - return ""; - } - - @Override - public F get(final T[] objs) { - if (objs == null || objs.length == 0) return null; - final Attribute attr = DataCallAttribute.load(objs[0].getClass()); - final Object keys = Array.newInstance(attr.type(), objs.length); - for (int i = 0; i < objs.length; i++) { - Array.set(keys, i, attr.get(objs[i])); - } - return (F) keys; - } - - @Override - public void set(final T[] objs, final F keys) { - if (objs == null || objs.length == 0) return; - final Attribute attr = DataCallAttribute.load(objs[0].getClass()); - for (int i = 0; i < objs.length; i++) { - attr.set(objs[i], (Serializable) Array.get(keys, i)); - } - } - -} diff --git a/src/com/wentch/redkale/source/DataCallAttribute.java b/src/com/wentch/redkale/source/DataCallAttribute.java deleted file mode 100644 index 3d569ae9e..000000000 --- a/src/com/wentch/redkale/source/DataCallAttribute.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import com.wentch.redkale.util.*; -import java.io.*; -import java.lang.reflect.*; -import java.util.concurrent.*; - -/** - * - * @author zhangjx - */ -public class DataCallAttribute implements Attribute { - - public static final DataCallAttribute instance = new DataCallAttribute(); - - private static final ConcurrentHashMap attributes = new ConcurrentHashMap<>(); - - static Attribute load(final Class clazz) { - Attribute rs = attributes.get(clazz); - if (rs != null) return rs; - synchronized (attributes) { - rs = attributes.get(clazz); - if (rs == null) { - Class cltmp = clazz; - do { - for (Field field : cltmp.getDeclaredFields()) { - if (field.getAnnotation(javax.persistence.Id.class) == null) continue; - try { - rs = Attribute.create(cltmp, field); - attributes.put(clazz, rs); - return rs; - } catch (RuntimeException e) { - } - } - } while ((cltmp = cltmp.getSuperclass()) != Object.class); - } - return rs; - } - } - - @Override - public Class type() { - return Serializable.class; - } - - @Override - public Class declaringClass() { - return Object.class; - } - - @Override - public String field() { - return ""; - } - - @Override - public Serializable get(final Object obj) { - if (obj == null) return null; - return load(obj.getClass()).get(obj); - } - - @Override - public void set(final Object obj, final Serializable key) { - if (obj == null) return; - load(obj.getClass()).set(obj, key); - } -} diff --git a/src/com/wentch/redkale/source/DataConnection.java b/src/com/wentch/redkale/source/DataConnection.java deleted file mode 100644 index 6ff5bae12..000000000 --- a/src/com/wentch/redkale/source/DataConnection.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -/** - * - * @author zhangjx - */ -public abstract class DataConnection { - - private final Object connection; - - protected DataConnection(Object connection) { - this.connection = connection; - } - - protected T getConnection() { - return (T) this.connection; - } - - public abstract boolean commit(); - - public abstract void rollback(); - - public abstract void close(); -} diff --git a/src/com/wentch/redkale/source/DataDefaultSource.java b/src/com/wentch/redkale/source/DataDefaultSource.java deleted file mode 100644 index 9a7b1b5a0..000000000 --- a/src/com/wentch/redkale/source/DataDefaultSource.java +++ /dev/null @@ -1,1554 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import static com.wentch.redkale.source.FilterNode.*; -import com.wentch.redkale.util.*; -import java.io.*; -import java.lang.reflect.*; -import java.net.*; -import java.sql.*; -import java.util.*; -import java.util.concurrent.atomic.*; -import java.util.function.*; -import java.util.logging.*; -import javax.annotation.*; -import javax.sql.*; -import javax.xml.stream.*; - -/** - * - * @author zhangjx - */ -@SuppressWarnings("unchecked") -public final class DataDefaultSource implements DataSource, Nameable, Function { - - public static final String DATASOURCE_CONFPATH = "DATASOURCE_CONFPATH"; - - static final String JDBC_CONNECTIONMAX = "javax.persistence.connection.limit"; - - static final String JDBC_URL = "javax.persistence.jdbc.url"; - - static final String JDBC_USER = "javax.persistence.jdbc.user"; - - static final String JDBC_PWD = "javax.persistence.jdbc.password"; - - static final String JDBC_DRIVER = "javax.persistence.jdbc.driver"; - - static final String JDBC_SOURCE = "javax.persistence.jdbc.source"; - - private static final Flipper FLIPPER_ONE = new Flipper(1); - - final Logger logger = Logger.getLogger(DataDefaultSource.class.getSimpleName()); - - final AtomicBoolean debug = new AtomicBoolean(logger.isLoggable(Level.FINEST)); - - final String name; - - final URL conf; - - final boolean cacheForbidden; - - private final boolean mysql; - - private final JDBCPoolSource readPool; - - private final JDBCPoolSource writePool; - - @Resource(name = "property.datasource.nodeid") - private int nodeid; - - @Resource(name = "$") - private DataSQLListener writeListener; - - @Resource(name = "$") - private DataCacheListener cacheListener; - - private static class DataJDBCConnection extends DataConnection { - - private final Connection sqlconn; - - private DataJDBCConnection(Connection c) { - super(c); - this.sqlconn = c; - try { - this.sqlconn.setAutoCommit(true); - } catch (Exception e) { - //do nothing - } - } - - @Override - public void close() { - try { - sqlconn.close(); - } catch (Exception e) { - //do nothing - } - } - - @Override - public boolean commit() { - try { - sqlconn.commit(); - return true; - } catch (Exception e) { - return false; - } - } - - @Override - public void rollback() { - try { - sqlconn.rollback(); - } catch (Exception e) { - //do nothing - } - } - } - - private final Function fullloader = (t) -> querySheet(false, false, t, null, null, (FilterNode) null).list(true); - - public DataDefaultSource() throws IOException { - this(""); - } - - public DataDefaultSource(final String unitName) throws IOException { - this(unitName, System.getProperty(DATASOURCE_CONFPATH) == null - ? DataDefaultSource.class.getResource("/META-INF/persistence.xml") - : new File(System.getProperty(DATASOURCE_CONFPATH)).toURI().toURL()); - } - - public DataDefaultSource(final String unitName, URL url) throws IOException { - if (url == null) url = this.getClass().getResource("/persistence.xml"); - InputStream in = url.openStream(); - Map map = loadProperties(in); - Properties readprop = null; - Properties writeprop = null; - if (unitName != null) { - readprop = map.get(unitName); - writeprop = readprop; - if (readprop == null) { - readprop = map.get(unitName + ".read"); - writeprop = map.get(unitName + ".write"); - } - } - if ((unitName == null || unitName.isEmpty()) || readprop == null) { - String key = null; - for (Map.Entry en : map.entrySet()) { - key = en.getKey(); - readprop = en.getValue(); - writeprop = readprop; - break; - } - if (key != null && (key.endsWith(".read") || key.endsWith(".write"))) { - if (key.endsWith(".read")) { - writeprop = map.get(key.substring(0, key.lastIndexOf('.')) + ".write"); - } else { - readprop = map.get(key.substring(0, key.lastIndexOf('.')) + ".read"); - } - } - } - if (readprop == null) throw new RuntimeException("not found persistence properties (unit:" + unitName + ")"); - this.name = unitName; - this.conf = url; - this.readPool = new JDBCPoolSource(this, "read", readprop); - this.writePool = new JDBCPoolSource(this, "write", writeprop); - this.mysql = this.writePool.isMysql(); - this.cacheForbidden = "NONE".equalsIgnoreCase(readprop.getProperty("shared-cache-mode")); - } - - public DataDefaultSource(String unitName, Properties readprop, Properties writeprop) { - this.name = unitName; - this.conf = null; - this.readPool = new JDBCPoolSource(this, "read", readprop); - this.writePool = new JDBCPoolSource(this, "write", writeprop); - this.mysql = this.writePool.isMysql(); - this.cacheForbidden = "NONE".equalsIgnoreCase(readprop.getProperty("shared-cache-mode")); - } - - public static Map create(final InputStream in) { - Map map = loadProperties(in); - Map maps = new HashMap<>(); - map.entrySet().stream().forEach((en) -> { - if (en.getKey().endsWith(".read") || en.getKey().endsWith(".write")) { - String key = en.getKey().substring(0, en.getKey().lastIndexOf('.')); - if (maps.containsKey(key)) return; - boolean read = en.getKey().endsWith(".read"); - Properties rp = read ? en.getValue() : map.get(key + ".read"); - Properties wp = read ? map.get(key + ".write") : en.getValue(); - maps.put(key, new Properties[]{rp, wp}); - } else { - maps.put(en.getKey(), new Properties[]{en.getValue(), en.getValue()}); - } - }); - Map result = new HashMap<>(); - maps.entrySet().stream().forEach((en) -> { - result.put(en.getKey(), new DataDefaultSource(en.getKey(), en.getValue()[0], en.getValue()[1])); - }); - return result; - } - - static Map loadProperties(final InputStream in0) { - final Map map = new LinkedHashMap(); - Properties result = new Properties(); - boolean flag = false; - try (final InputStream in = in0) { - XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(in); - while (reader.hasNext()) { - int event = reader.next(); - if (event == XMLStreamConstants.START_ELEMENT) { - if ("persistence-unit".equalsIgnoreCase(reader.getLocalName())) { - if (!result.isEmpty()) result = new Properties(); - map.put(reader.getAttributeValue(null, "name"), result); - flag = true; - } else if (flag && "property".equalsIgnoreCase(reader.getLocalName())) { - String name = reader.getAttributeValue(null, "name"); - String value = reader.getAttributeValue(null, "value"); - if (name == null) continue; - result.put(name, value); - } else if (flag && "shared-cache-mode".equalsIgnoreCase(reader.getLocalName())) { - result.put(reader.getLocalName(), reader.getElementText()); - } - } - } - in.close(); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - return map; - } - - static ConnectionPoolDataSource createDataSource(Properties property) { - try { - return createDataSource(property.getProperty(JDBC_SOURCE, property.getProperty(JDBC_DRIVER)), - property.getProperty(JDBC_URL), property.getProperty(JDBC_USER), property.getProperty(JDBC_PWD)); - } catch (Exception ex) { - throw new RuntimeException("(" + property + ") have no jdbc parameters", ex); - } - } - - static ConnectionPoolDataSource createDataSource(final String source0, String url, String user, String password) throws Exception { - String source = source0; - if (source0.contains("Driver")) { //为了兼容JPA的配置文件 - switch (source0) { - case "org.mariadb.jdbc.Driver": - source = "org.mariadb.jdbc.MySQLDataSource"; - break; - case "com.mysql.jdbc.Driver": - source = "com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource"; - break; - case "oracle.jdbc.driver.OracleDriver": - source = "oracle.jdbc.pool.OracleConnectionPoolDataSource"; - break; - case "com.microsoft.sqlserver.jdbc.SQLServerDriver": - source = "com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource"; - break; - } - } - final Class clazz = Class.forName(source); - Object pdsource = clazz.newInstance(); - Method seturlm; - try { - seturlm = clazz.getMethod("setUrl", String.class); - } catch (Exception e) { - seturlm = clazz.getMethod("setURL", String.class); - } - seturlm.invoke(pdsource, url); - clazz.getMethod("setUser", String.class).invoke(pdsource, user); - clazz.getMethod("setPassword", String.class).invoke(pdsource, password); - return (ConnectionPoolDataSource) pdsource; - } - - @Override - public final String name() { - return name; - } - - @Override - public DataConnection createReadConnection() { - return new DataJDBCConnection(createReadSQLConnection()); - } - - @Override - public DataConnection createWriteConnection() { - return new DataJDBCConnection(createWriteSQLConnection()); - } - - public void close() { - readPool.close(); - writePool.close(); - } - - public String getName() { - return name; - } - - private Connection createReadSQLConnection() { - return readPool.poll(); - } - - private Connection createWriteSQLConnection() { - return writePool.poll(); - } - - private void closeSQLConnection(final Connection sqlconn) { - if (sqlconn == null) return; - try { - sqlconn.close(); - } catch (Exception e) { - logger.log(Level.WARNING, "closeSQLConnection abort", e); - } - } - - public void execute(String... sqls) { - Connection conn = createWriteSQLConnection(); - try { - execute(conn, sqls); - } finally { - closeSQLConnection(conn); - } - } - - public void execute(final DataConnection conn, String... sqls) { - execute((Connection) conn.getConnection(), sqls); - } - - private void execute(final Connection conn, String... sqls) { - if (sqls.length == 0) return; - try { - final Statement stmt = conn.createStatement(); - for (String sql : sqls) { - stmt.execute(sql); - } - stmt.close(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - @Override - public EntityInfo apply(Class t) { - return loadEntityInfo(t); - } - - private EntityInfo loadEntityInfo(Class clazz) { - return EntityInfo.load(clazz, this.nodeid, this.cacheForbidden, fullloader); - } - - /** - * 将entity的对象全部加载到Cache中去,如果clazz没有被@javax.persistence.Cacheable注解则不做任何事 - *

- * @param - * @param clazz - */ - @Override - public void refreshCache(Class clazz) { - EntityInfo info = loadEntityInfo(clazz); - EntityCache cache = info.getCache(); - if (cache == null) return; - cache.fullLoad(queryList(clazz, (FilterNode) null)); - } - - //----------------------insertCache----------------------------- - /** - * 新增对象, 必须是Entity对象 - * - * @param - * @param values - */ - @Override - public void insert(T... values) { - if (values.length == 0) return; - final EntityInfo info = loadEntityInfo((Class) values[0].getClass()); - if (info.isVirtualEntity()) { - insert(null, info, values); - return; - } - Connection conn = createWriteSQLConnection(); - try { - insert(conn, info, values); - } finally { - closeSQLConnection(conn); - } - } - - /** - * 新增对象, 必须是Entity对象 - * - * @param - * @param conn - * @param values - */ - @Override - public void insert(final DataConnection conn, T... values) { - if (values.length == 0) return; - final EntityInfo info = loadEntityInfo((Class) values[0].getClass()); - insert((Connection) conn.getConnection(), info, values); - } - - private void insert(final Connection conn, final EntityInfo info, T... values) { - if (values.length == 0) return; - try { - final EntityCache cache = info.getCache(); - if (!info.isVirtualEntity()) { - final String sql = info.insertSQL; - final PreparedStatement prestmt = info.autoGenerated - ? conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) : conn.prepareStatement(sql); - final Class primaryType = info.getPrimary().type(); - final Attribute primary = info.getPrimary(); - final boolean distributed = info.distributed; - Attribute[] attrs = info.insertAttributes; - String[] sqls = null; - if (distributed && !info.initedPrimaryValue && primaryType.isPrimitive()) { - synchronized (info) { - if (!info.initedPrimaryValue) { - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT MAX(" + info.getPrimarySQLColumn() + ") FROM " + info.getTable()); - if (rs.next()) { - if (primaryType == int.class) { - int v = rs.getInt(1) / info.allocationSize; - if (v > info.primaryValue.get()) info.primaryValue.set(v); - } else { - long v = rs.getLong(1) / info.allocationSize; - if (v > info.primaryValue.get()) info.primaryValue.set(v); - } - } - rs.close(); - stmt.close(); - if (info.distributeTables != null) { - for (final Class t : info.distributeTables) { - EntityInfo infox = loadEntityInfo(t); - stmt = conn.createStatement(); - rs = stmt.executeQuery("SELECT MAX(" + info.getPrimarySQLColumn() + ") FROM " + infox.getTable()); // 必须是同一字段名 - if (rs.next()) { - if (primaryType == int.class) { - int v = rs.getInt(1) / info.allocationSize; - if (v > info.primaryValue.get()) info.primaryValue.set(v); - } else { - long v = rs.getLong(1) / info.allocationSize; - if (v > info.primaryValue.get()) info.primaryValue.set(v); - } - } - rs.close(); - stmt.close(); - } - } - info.initedPrimaryValue = true; - } - } - } - if (writeListener == null) { - for (final T value : values) { - int i = 0; - if (distributed) info.createPrimaryValue(value); - for (Attribute attr : attrs) { - prestmt.setObject(++i, attr.get(value)); - } - prestmt.addBatch(); - } - } else { - char[] sqlchars = sql.toCharArray(); - sqls = new String[values.length]; - CharSequence[] ps = new CharSequence[attrs.length]; - int index = 0; - for (final T value : values) { - int i = 0; - if (distributed) info.createPrimaryValue(value); - for (Attribute attr : attrs) { - Object a = attr.get(value); - ps[i] = formatToString(a); - prestmt.setObject(++i, a); - } - prestmt.addBatch(); - //----------------------------- - StringBuilder sb = new StringBuilder(128); - i = 0; - for (char ch : sqlchars) { - if (ch == '?') { - sb.append(ps[i++]); - } else { - sb.append(ch); - } - } - sqls[index++] = sb.toString(); - } - } - prestmt.executeBatch(); - if (writeListener != null) writeListener.insert(sqls); - if (info.autoGenerated) { - ResultSet set = prestmt.getGeneratedKeys(); - int i = -1; - while (set.next()) { - if (primaryType == int.class) { - primary.set(values[++i], set.getInt(1)); - } else if (primaryType == long.class) { - primary.set(values[++i], set.getLong(1)); - } else { - primary.set(values[++i], set.getObject(1)); - } - } - set.close(); - } - prestmt.close(); - //------------------------------------------------------------ - if (debug.get()) { - char[] sqlchars = sql.toCharArray(); - for (final T value : values) { - //----------------------------- - StringBuilder sb = new StringBuilder(128); - int i = 0; - for (char ch : sqlchars) { - if (ch == '?') { - Object obj = attrs[i++].get(value); - if (obj != null && obj.getClass().isArray()) { - sb.append("'[length=").append(java.lang.reflect.Array.getLength(obj)).append("]'"); - } else { - sb.append(formatToString(obj)); - } - } else { - sb.append(ch); - } - } - logger.finest(info.getType().getSimpleName() + " insert sql=" + sb.toString().replaceAll("(\r|\n)", "\\n")); - } - } - } - if (cache != null) { - for (final T value : values) { - cache.insert(value); - } - if (cacheListener != null) cacheListener.insertCache(info.getType(), values); - } - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public void insertCache(Class clazz, T... values) { - if (values.length == 0) return; - final EntityInfo info = loadEntityInfo(clazz); - final EntityCache cache = info.getCache(); - if (cache == null) return; - for (T value : values) { - cache.insert(value); - } - } - - //-------------------------deleteCache-------------------------- - /** - * 删除对象, 必须是Entity对象 - * - * @param - * @param values - */ - @Override - public void delete(T... values) { - if (values.length == 0) return; - final EntityInfo info = loadEntityInfo((Class) values[0].getClass()); - if (info.isVirtualEntity()) { - delete(null, info, values); - return; - } - Connection conn = createWriteSQLConnection(); - try { - delete(conn, info, values); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public void delete(final DataConnection conn, T... values) { - if (values.length == 0) return; - final EntityInfo info = loadEntityInfo((Class) values[0].getClass()); - delete((Connection) conn.getConnection(), info, values); - } - - private void delete(final Connection conn, final EntityInfo info, T... values) { - if (values.length == 0) return; - final Attribute primary = info.getPrimary(); - Serializable[] ids = new Serializable[values.length]; - int i = 0; - for (final T value : values) { - ids[i++] = (Serializable) primary.get(value); - } - delete(conn, info, ids); - } - - @Override - public void delete(Class clazz, Serializable... ids) { - final EntityInfo info = loadEntityInfo(clazz); - if (info.isVirtualEntity()) { - delete(null, info, ids); - return; - } - Connection conn = createWriteSQLConnection(); - try { - delete(conn, info, ids); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public void delete(final DataConnection conn, Class clazz, Serializable... ids) { - delete((Connection) conn.getConnection(), loadEntityInfo(clazz), ids); - } - - private void delete(final Connection conn, final EntityInfo info, Serializable... keys) { - if (keys.length == 0) return; - try { - if (!info.isVirtualEntity()) { - String sql = "DELETE FROM " + info.getTable() + " WHERE " + info.getPrimarySQLColumn() + " IN " + formatToString(keys); - if (debug.get()) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql); - final Statement stmt = conn.createStatement(); - stmt.execute(sql); - stmt.close(); - if (writeListener != null) writeListener.delete(sql); - } - //------------------------------------ - final EntityCache cache = info.getCache(); - if (cache == null) return; - for (Serializable key : keys) { - cache.delete(key); - } - if (cacheListener != null) cacheListener.deleteCache(info.getType(), keys); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - @Override - public void delete(Class clazz, FilterNode node) { - final EntityInfo info = loadEntityInfo(clazz); - if (info.isVirtualEntity()) { - delete(null, info, node); - return; - } - Connection conn = createWriteSQLConnection(); - try { - delete(conn, info, node); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public void delete(final DataConnection conn, Class clazz, FilterNode node) { - delete((Connection) conn.getConnection(), loadEntityInfo(clazz), node); - } - - private void delete(final Connection conn, final EntityInfo info, final FilterNode node) { - try { - if (!info.isVirtualEntity()) { - Map joinTabalis = node.getJoinTabalis(); - CharSequence join = node.createSQLJoin(this, joinTabalis, info); - CharSequence where = node.createSQLExpress(info, joinTabalis); - String sql = "DELETE " + (mysql ? "a" : "") + " FROM " + info.getTable() + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)); - if (debug.get()) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql); - final Statement stmt = conn.createStatement(); - stmt.execute(sql); - stmt.close(); - if (writeListener != null) writeListener.delete(sql); - } - //------------------------------------ - final EntityCache cache = info.getCache(); - if (cache == null) return; - Serializable[] ids = cache.delete(node); - if (cacheListener != null) cacheListener.deleteCache(info.getType(), ids); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public void deleteCache(Class clazz, Serializable... ids) { - if (ids.length == 0) return; - final EntityInfo info = loadEntityInfo(clazz); - final EntityCache cache = info.getCache(); - if (cache == null) return; - for (Serializable id : ids) { - cache.delete(id); - } - } - - //------------------------update--------------------------- - /** - * 更新对象, 必须是Entity对象 - * - * @param - * @param values - */ - @Override - public void update(T... values) { - if (values.length == 0) return; - final EntityInfo info = loadEntityInfo((Class) values[0].getClass()); - if (info.isVirtualEntity()) { - update(null, info, values); - return; - } - Connection conn = createWriteSQLConnection(); - try { - update(conn, info, values); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public void update(final DataConnection conn, T... values) { - if (values.length == 0) return; - final EntityInfo info = loadEntityInfo((Class) values[0].getClass()); - update((Connection) conn.getConnection(), info, values); - } - - private void update(final Connection conn, final EntityInfo info, T... values) { - try { - Class clazz = info.getType(); - if (!info.isVirtualEntity()) { - if (debug.get()) logger.finest(clazz.getSimpleName() + " update sql=" + info.updateSQL); - final Attribute primary = info.getPrimary(); - final PreparedStatement prestmt = conn.prepareStatement(info.updateSQL); - Attribute[] attrs = info.updateAttributes; - String[] sqls = null; - if (writeListener == null) { - for (final T value : values) { - int i = 0; - for (Attribute attr : attrs) { - prestmt.setObject(++i, attr.get(value)); - } - prestmt.setObject(++i, primary.get(value)); - prestmt.addBatch(); - } - } else { - char[] sqlchars = info.updateSQL.toCharArray(); - sqls = new String[values.length]; - CharSequence[] ps = new CharSequence[attrs.length]; - int index = 0; - for (final T value : values) { - int i = 0; - for (Attribute attr : attrs) { - Object a = attr.get(value); - ps[i] = formatToString(a); - prestmt.setObject(++i, a); - } - prestmt.setObject(++i, primary.get(value)); - prestmt.addBatch(); - //----------------------------- - StringBuilder sb = new StringBuilder(128); - i = 0; - for (char ch : sqlchars) { - if (ch == '?') { - sb.append(ps[i++]); - } else { - sb.append(ch); - } - } - sqls[index++] = sb.toString(); - } - } - prestmt.executeBatch(); - prestmt.close(); - if (writeListener != null) writeListener.update(sqls); - } - //--------------------------------------------------- - final EntityCache cache = info.getCache(); - if (cache == null) return; - for (final T value : values) { - cache.update(value); - } - if (cacheListener != null) cacheListener.updateCache(clazz, values); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - /** - * 根据主键值更新对象的column对应的值, 必须是Entity Class - * - * @param - * @param clazz - * @param id - * @param column - * @param value - */ - @Override - public void updateColumn(Class clazz, Serializable id, String column, Serializable value) { - final EntityInfo info = loadEntityInfo(clazz); - if (info.isVirtualEntity()) { - updateColumn(null, info, id, column, value); - return; - } - Connection conn = createWriteSQLConnection(); - try { - updateColumn(conn, info, id, column, value); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public void updateColumn(DataConnection conn, Class clazz, Serializable id, String column, Serializable value) { - updateColumn((Connection) conn.getConnection(), loadEntityInfo(clazz), id, column, value); - } - - private void updateColumn(Connection conn, final EntityInfo info, Serializable id, String column, Serializable value) { - try { - if (!info.isVirtualEntity()) { - String sql = "UPDATE " + info.getTable() + " SET " + info.getSQLColumn(null, column) + " = " - + formatToString(value) + " WHERE " + info.getPrimarySQLColumn() + " = " + formatToString(id); - if (debug.get()) logger.finest(info.getType().getSimpleName() + " update sql=" + sql); - final Statement stmt = conn.createStatement(); - stmt.execute(sql); - stmt.close(); - if (writeListener != null) writeListener.update(sql); - } - //--------------------------------------------------- - final EntityCache cache = info.getCache(); - if (cache == null) return; - T rs = cache.update(id, info.getAttribute(column), value); - if (cacheListener != null) cacheListener.updateCache(info.getType(), rs); - } catch (SQLException e) { - throw new RuntimeException(e); - } finally { - if (conn != null) closeSQLConnection(conn); - } - } - - /** - * 根据主键值给对象的column对应的值+incvalue, 必须是Entity Class - * - * @param - * @param clazz - * @param id - * @param column - * @param incvalue - */ - @Override - public void updateColumnIncrement(Class clazz, Serializable id, String column, long incvalue) { - final EntityInfo info = loadEntityInfo(clazz); - if (info.isVirtualEntity()) { - updateColumnIncrement(null, info, id, column, incvalue); - return; - } - Connection conn = createWriteSQLConnection(); - try { - updateColumnIncrement(conn, info, id, column, incvalue); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public void updateColumnIncrement(DataConnection conn, Class clazz, Serializable id, String column, long incvalue) { - updateColumnIncrement((Connection) conn.getConnection(), loadEntityInfo(clazz), id, column, incvalue); - } - - private void updateColumnIncrement(Connection conn, final EntityInfo info, Serializable id, String column, long incvalue) { - try { - if (!info.isVirtualEntity()) { - String col = info.getSQLColumn(null, column); - String sql = "UPDATE " + info.getTable() + " SET " + col + " = " + col + " + (" + incvalue - + ") WHERE " + info.getPrimarySQLColumn() + " = " + formatToString(id); - if (debug.get()) logger.finest(info.getType().getSimpleName() + " update sql=" + sql); - final Statement stmt = conn.createStatement(); - stmt.execute(sql); - stmt.close(); - if (writeListener != null) writeListener.update(sql); - } - //--------------------------------------------------- - final EntityCache cache = info.getCache(); - if (cache == null) return; - Attribute attr = info.getAttribute(column); - T value = cache.updateColumnIncrement(id, attr, incvalue); - if (value != null && cacheListener != null) cacheListener.updateCache(info.getType(), value); - } catch (SQLException e) { - throw new RuntimeException(e); - } finally { - if (conn != null) closeSQLConnection(conn); - } - } - - /** - * 根据主键值给对象的column对应的值 & andvalue, 必须是Entity Class - * - * @param - * @param clazz - * @param id - * @param column - * @param andvalue - */ - @Override - public void updateColumnAnd(Class clazz, Serializable id, String column, long andvalue) { - final EntityInfo info = loadEntityInfo(clazz); - if (info.isVirtualEntity()) { - updateColumnAnd(null, info, id, column, andvalue); - return; - } - Connection conn = createWriteSQLConnection(); - try { - updateColumnAnd(conn, info, id, column, andvalue); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public void updateColumnAnd(DataConnection conn, Class clazz, Serializable id, String column, long andvalue) { - updateColumnAnd((Connection) conn.getConnection(), loadEntityInfo(clazz), id, column, andvalue); - } - - private void updateColumnAnd(Connection conn, final EntityInfo info, Serializable id, String column, long andvalue) { - try { - if (!info.isVirtualEntity()) { - String col = info.getSQLColumn(null, column); - String sql = "UPDATE " + info.getTable() + " SET " + col + " = " + col + " & (" + andvalue - + ") WHERE " + info.getPrimarySQLColumn() + " = " + formatToString(id); - if (debug.get()) logger.finest(info.getType().getSimpleName() + " update sql=" + sql); - final Statement stmt = conn.createStatement(); - stmt.execute(sql); - stmt.close(); - if (writeListener != null) writeListener.update(sql); - } - //--------------------------------------------------- - final EntityCache cache = info.getCache(); - if (cache == null) return; - Attribute attr = info.getAttribute(column); - T value = cache.updateColumnAnd(id, attr, andvalue); - if (value != null && cacheListener != null) cacheListener.updateCache(info.getType(), value); - } catch (SQLException e) { - throw new RuntimeException(e); - } finally { - if (conn != null) closeSQLConnection(conn); - } - } - - /** - * 根据主键值给对象的column对应的值 | andvalue, 必须是Entity Class - * - * @param - * @param clazz - * @param id - * @param column - * @param orvalue - */ - @Override - public void updateColumnOr(Class clazz, Serializable id, String column, long orvalue) { - final EntityInfo info = loadEntityInfo(clazz); - if (info.isVirtualEntity()) { - updateColumnOr(null, info, id, column, orvalue); - return; - } - Connection conn = createWriteSQLConnection(); - try { - updateColumnOr(conn, info, id, column, orvalue); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public void updateColumnOr(DataConnection conn, Class clazz, Serializable id, String column, long orvalue) { - updateColumnOr((Connection) conn.getConnection(), loadEntityInfo(clazz), id, column, orvalue); - } - - private void updateColumnOr(Connection conn, final EntityInfo info, Serializable id, String column, long orvalue) { - try { - if (!info.isVirtualEntity()) { - String col = info.getSQLColumn(null, column); - String sql = "UPDATE " + info.getTable() + " SET " + col + " = " + col + " | (" + orvalue - + ") WHERE " + info.getPrimarySQLColumn() + " = " + formatToString(id); - if (debug.get()) logger.finest(info.getType().getSimpleName() + " update sql=" + sql); - final Statement stmt = conn.createStatement(); - stmt.execute(sql); - stmt.close(); - if (writeListener != null) writeListener.update(sql); - } - //--------------------------------------------------- - final EntityCache cache = info.getCache(); - if (cache == null) return; - Attribute attr = info.getAttribute(column); - T value = cache.updateColumnOr(id, attr, orvalue); - if (value != null && cacheListener != null) cacheListener.updateCache(info.getType(), value); - } catch (SQLException e) { - throw new RuntimeException(e); - } finally { - if (conn != null) closeSQLConnection(conn); - } - } - - /** - * 更新对象指定的一些字段, 必须是Entity对象 - * - * @param - * @param value - * @param columns - */ - @Override - public void updateColumns(final T value, final String... columns) { - final EntityInfo info = loadEntityInfo((Class) value.getClass()); - if (info.isVirtualEntity()) { - updateColumns(null, info, value, columns); - return; - } - Connection conn = createWriteSQLConnection(); - try { - updateColumns(conn, info, value, columns); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public void updateColumns(final DataConnection conn, final T value, final String... columns) { - updateColumns((Connection) conn.getConnection(), loadEntityInfo((Class) value.getClass()), value, columns); - } - - private void updateColumns(final Connection conn, final EntityInfo info, final T value, final String... columns) { - if (value == null || columns.length < 1) return; - try { - final Class clazz = (Class) value.getClass(); - StringBuilder setsql = new StringBuilder(); - final Serializable id = info.getPrimary().get(value); - final List> attrs = new ArrayList<>(); - final boolean virtual = info.isVirtualEntity(); - for (String col : columns) { - Attribute attr = info.getUpdateAttribute(col); - if (attr == null) continue; - attrs.add(attr); - if (!virtual) { - if (setsql.length() > 0) setsql.append(','); - setsql.append(info.getSQLColumn(null, col)).append(" = ").append(formatToString(attr.get(value))); - } - } - if (!virtual) { - String sql = "UPDATE " + info.getTable() + " SET " + setsql + " WHERE " + info.getPrimarySQLColumn() + " = " + formatToString(id); - if (debug.get()) logger.finest(value.getClass().getSimpleName() + ": " + sql); - final Statement stmt = conn.createStatement(); - stmt.execute(sql); - stmt.close(); - if (writeListener != null) writeListener.update(sql); - } - //--------------------------------------------------- - final EntityCache cache = info.getCache(); - if (cache == null) return; - T rs = cache.update(value, attrs); - if (cacheListener != null) cacheListener.updateCache(clazz, rs); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public void updateCache(Class clazz, T... values) { - if (values.length == 0) return; - final EntityInfo info = loadEntityInfo(clazz); - final EntityCache cache = info.getCache(); - if (cache == null) return; - for (T value : values) { - cache.update(value); - } - } - - public void reloadCache(Class clazz, Serializable... ids) { - final EntityInfo info = loadEntityInfo(clazz); - final EntityCache cache = info.getCache(); - if (cache == null) return; - String column = info.getPrimary().field(); - for (Serializable id : ids) { - Sheet sheet = querySheet(false, true, clazz, null, FLIPPER_ONE, FilterNode.create(column, id)); - T value = sheet.isEmpty() ? null : sheet.list().get(0); - if (value != null) cache.update(value); - } - } - - //-----------------------getNumberResult----------------------------- - @Override - public Number getNumberResult(final Class entityClass, final Reckon reckon, final String column) { - return getNumberResult(entityClass, reckon, column, (FilterNode) null); - } - - @Override - public Number getNumberResult(final Class entityClass, final Reckon reckon, final String column, FilterBean bean) { - return getNumberResult(entityClass, reckon, column, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public Number getNumberResult(final Class entityClass, final Reckon reckon, final String column, final FilterNode node) { - final Connection conn = createReadSQLConnection(); - try { - final EntityInfo info = loadEntityInfo(entityClass); - final EntityCache cache = info.getCache(); - if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) { - if (node == null || node.isCacheUseable(this)) { - return cache.getNumberResult(reckon, column, node); - } - } - final Map joinTabalis = node == null ? null : node.getJoinTabalis(); - final CharSequence join = node == null ? null : node.createSQLJoin(this, joinTabalis, info); - final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis); - final String sql = "SELECT " + reckon.getColumn((column == null || column.isEmpty() ? "*" : ("a." + column))) + " FROM " + info.getTable() + " a" - + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)); - if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql); - final PreparedStatement prestmt = conn.prepareStatement(sql); - Number rs = null; - ResultSet set = prestmt.executeQuery(); - if (set.next()) { - rs = (Number) set.getObject(1); - } - set.close(); - prestmt.close(); - return rs; - } catch (SQLException e) { - throw new RuntimeException(e); - } finally { - if (conn != null) closeSQLConnection(conn); - } - } - - //-----------------------getMapResult----------------------------- - @Override - public Map getMapResult(Class entityClass, final String keyColumn, Reckon reckon, final String reckonColumn) { - return getMapResult(entityClass, keyColumn, reckon, reckonColumn, (FilterNode) null); - } - - @Override - public Map getMapResult(Class entityClass, final String keyColumn, Reckon reckon, final String reckonColumn, FilterBean bean) { - return getMapResult(entityClass, keyColumn, reckon, reckonColumn, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public Map getMapResult(final Class entityClass, final String keyColumn, final Reckon reckon, final String reckonColumn, FilterNode node) { - final Connection conn = createReadSQLConnection(); - try { - final EntityInfo info = loadEntityInfo(entityClass); - final EntityCache cache = info.getCache(); - if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) { - if (node == null || node.isCacheUseable(this)) { - return cache.getMapResult(keyColumn, reckon, reckonColumn, node); - } - } - final String sqlkey = info.getSQLColumn(null, keyColumn); - final Map joinTabalis = node == null ? null : node.getJoinTabalis(); - final CharSequence join = node == null ? null : node.createSQLJoin(this, joinTabalis, info); - final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis); - final String sql = "SELECT a." + sqlkey + ", " + reckon.getColumn((reckonColumn == null || reckonColumn.isEmpty() ? "*" : ("a." + reckonColumn))) - + " FROM " + info.getTable() + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)) + " GROUP BY a." + sqlkey; - if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql); - final PreparedStatement prestmt = conn.prepareStatement(sql); - Map rs = new LinkedHashMap<>(); - ResultSet set = prestmt.executeQuery(); - ResultSetMetaData rsd = set.getMetaData(); - boolean smallint = rsd.getColumnType(1) == Types.SMALLINT; - while (set.next()) { - rs.put((K) (smallint ? set.getShort(1) : set.getObject(1)), (V) set.getObject(2)); - } - set.close(); - prestmt.close(); - return rs; - } catch (SQLException e) { - throw new RuntimeException(e); - } finally { - if (conn != null) closeSQLConnection(conn); - } - } - - //-----------------------find---------------------------- - /** - * 根据主键获取对象 - * - * @param - * @param clazz - * @param pk - * @return - */ - @Override - public T find(Class clazz, Serializable pk) { - return find(clazz, (SelectColumn) null, pk); - } - - @Override - public T find(Class clazz, final SelectColumn selects, Serializable pk) { - final EntityInfo info = loadEntityInfo(clazz); - final EntityCache cache = info.getCache(); - if (cache != null && cache.isFullLoaded()) return cache.find(selects, pk); - - final Connection conn = createReadSQLConnection(); - try { - final SelectColumn sels = selects; - final String sql = "SELECT * FROM " + info.getTable() + " WHERE " + info.getPrimarySQLColumn() + " = " + formatToString(pk); - if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " find sql=" + sql); - final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - final ResultSet set = ps.executeQuery(); - T rs = set.next() ? info.getValue(sels, set) : null; - set.close(); - ps.close(); - return rs; - } catch (Exception ex) { - throw new RuntimeException(ex); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public T findByColumn(final Class clazz, final String column, final Serializable key) { - return find(clazz, null, FilterNode.create(column, key)); - } - - @Override - public T find(final Class clazz, final FilterBean bean) { - return find(clazz, null, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public T find(final Class clazz, final FilterNode node) { - return find(clazz, null, node); - } - - public T find(final Class clazz, final SelectColumn selects, final FilterNode node) { - final EntityInfo info = loadEntityInfo(clazz); - final EntityCache cache = info.getCache(); - if (cache != null && cache.isFullLoaded() && (node == null || node.isCacheUseable(this))) return cache.find(selects, node); - - final Connection conn = createReadSQLConnection(); - try { - final SelectColumn sels = selects; - final Map joinTabalis = node == null ? null : node.getJoinTabalis(); - final CharSequence join = node == null ? null : node.createSQLJoin(this, joinTabalis, info); - final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis); - final String sql = "SELECT a.* FROM " + info.getTable() + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)); - if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " find sql=" + sql); - final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - final ResultSet set = ps.executeQuery(); - T rs = set.next() ? info.getValue(sels, set) : null; - set.close(); - ps.close(); - return rs; - } catch (Exception ex) { - throw new RuntimeException(ex); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public boolean exists(Class clazz, Serializable pk) { - final EntityInfo info = loadEntityInfo(clazz); - final EntityCache cache = info.getCache(); - if (cache != null && cache.isFullLoaded()) return cache.exists(pk); - - final Connection conn = createReadSQLConnection(); - try { - final String sql = "SELECT COUNT(*) FROM " + info.getTable() + " WHERE " + info.getPrimarySQLColumn() + " = " + formatToString(pk); - if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " exists sql=" + sql); - final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - final ResultSet set = ps.executeQuery(); - boolean rs = set.next() ? (set.getInt(1) > 0) : false; - set.close(); - ps.close(); - return rs; - } catch (Exception ex) { - throw new RuntimeException(ex); - } finally { - closeSQLConnection(conn); - } - } - - @Override - public boolean exists(final Class clazz, final FilterBean bean) { - return exists(clazz, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public boolean exists(final Class clazz, final FilterNode node) { - final EntityInfo info = loadEntityInfo(clazz); - final EntityCache cache = info.getCache(); - if (cache != null && cache.isFullLoaded() && (node == null || node.isCacheUseable(this))) return cache.exists(node); - - final Connection conn = createReadSQLConnection(); - try { - final Map joinTabalis = node == null ? null : node.getJoinTabalis(); - final CharSequence join = node == null ? null : node.createSQLJoin(this, joinTabalis, info); - final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis); - final String sql = "SELECT COUNT(" + info.getPrimarySQLColumn("a") + ") FROM " + info.getTable() + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)); - if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " exists sql=" + sql); - final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - final ResultSet set = ps.executeQuery(); - boolean rs = set.next() ? (set.getInt(1) > 0) : false; - set.close(); - ps.close(); - return rs; - } catch (Exception ex) { - throw new RuntimeException(ex); - } finally { - closeSQLConnection(conn); - } - } - - //-----------------------list set---------------------------- - @Override - public HashSet queryColumnSet(String selectedColumn, Class clazz, String column, Serializable key) { - return queryColumnSet(selectedColumn, clazz, FilterNode.create(column, key)); - } - - @Override - public HashSet queryColumnSet(String selectedColumn, Class clazz, FilterBean bean) { - return new LinkedHashSet<>(queryColumnList(selectedColumn, clazz, bean)); - } - - @Override - public HashSet queryColumnSet(String selectedColumn, Class clazz, FilterNode node) { - return new LinkedHashSet<>(queryColumnList(selectedColumn, clazz, node)); - } - - @Override - public List queryColumnList(String selectedColumn, Class clazz, String column, Serializable key) { - return queryColumnList(selectedColumn, clazz, FilterNode.create(column, key)); - } - - @Override - public List queryColumnList(String selectedColumn, Class clazz, FilterBean bean) { - return (List) queryColumnSheet(selectedColumn, clazz, null, bean).list(true); - } - - @Override - public List queryColumnList(String selectedColumn, Class clazz, FilterNode node) { - return (List) queryColumnSheet(selectedColumn, clazz, null, node).list(true); - } - - /** - * 根据过滤对象FilterBean查询对象集合 - * - * @param - * @param - * @param clazz - * @param bean - * @return - */ - @Override - public Map queryMap(final Class clazz, final FilterBean bean) { - return queryMap(clazz, null, bean); - } - - @Override - public Map queryMap(final Class clazz, final FilterNode node) { - return queryMap(clazz, null, node); - } - - @Override - public Map queryMap(final Class clazz, final SelectColumn selects, final FilterBean bean) { - return formatMap(clazz, queryList(clazz, selects, null, bean)); - } - - @Override - public Map queryMap(final Class clazz, final SelectColumn selects, final FilterNode node) { - return formatMap(clazz, queryList(clazz, selects, null, node)); - } - - private Map formatMap(final Class clazz, Collection list) { - Map map = new LinkedHashMap<>(); - if (list == null || list.isEmpty()) return map; - final Attribute attr = (Attribute) loadEntityInfo(clazz).getPrimary(); - for (T t : list) { - map.put(attr.get(t), t); - } - return map; - } - - /** - * 根据指定字段值查询对象集合 - * - * @param - * @param clazz - * @param column - * @param key - * @return - */ - @Override - public List queryList(Class clazz, String column, Serializable key) { - return queryList(clazz, FilterNode.create(column, key)); - } - - /** - * 根据过滤对象FilterBean查询对象集合 - * - * @param - * @param clazz - * @param bean - * @return - */ - @Override - public List queryList(final Class clazz, final FilterBean bean) { - return queryList(clazz, (SelectColumn) null, bean); - } - - @Override - public List queryList(final Class clazz, final FilterNode node) { - return queryList(clazz, (SelectColumn) null, node); - } - - /** - * 根据过滤对象FilterBean查询对象集合, 对象只填充或排除SelectField指定的字段 - * - * @param - * @param clazz - * @param selects - * @param bean - * @return - */ - @Override - public List queryList(final Class clazz, final SelectColumn selects, final FilterBean bean) { - return queryList(clazz, selects, (Flipper) null, bean); - } - - @Override - public List queryList(final Class clazz, final SelectColumn selects, final FilterNode node) { - return queryList(clazz, selects, (Flipper) null, node); - } - - @Override - public List queryList(Class clazz, final Flipper flipper, String column, Serializable key) { - return queryList(clazz, flipper, FilterNode.create(column, key)); - } - - @Override - public List queryList(final Class clazz, final Flipper flipper, final FilterNode node) { - return queryList(clazz, null, flipper, node); - } - - @Override - public List queryList(final Class clazz, final Flipper flipper, final FilterBean bean) { - return queryList(clazz, null, flipper, bean); - } - - @Override - public List queryList(final Class clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) { - return querySheet(true, false, clazz, selects, flipper, node).list(true); - } - - @Override - public List queryList(final Class clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) { - return querySheet(true, false, clazz, selects, flipper, FilterNodeBean.createFilterNode(bean)).list(true); - } - - //-----------------------sheet---------------------------- - /** - * 根据指定参数查询对象某个字段的集合 - *

- * @param - * @param - * @param selectedColumn - * @param clazz - * @param flipper - * @param bean - * @return - */ - @Override - public Sheet queryColumnSheet(String selectedColumn, Class clazz, final Flipper flipper, final FilterBean bean) { - return queryColumnSheet(selectedColumn, clazz, flipper, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public Sheet queryColumnSheet(String selectedColumn, Class clazz, final Flipper flipper, final FilterNode node) { - Sheet sheet = querySheet(true, true, clazz, SelectColumn.createIncludes(selectedColumn), flipper, node); - final Sheet rs = new Sheet<>(); - if (sheet.isEmpty()) return rs; - rs.setTotal(sheet.getTotal()); - final EntityInfo info = loadEntityInfo(clazz); - final Attribute selected = (Attribute) info.getAttribute(selectedColumn); - final List list = new ArrayList<>(); - for (T t : sheet.getRows()) { - list.add(selected.get(t)); - } - rs.setRows(list); - return rs; - } - - /** - * 根据过滤对象FilterBean和翻页对象Flipper查询一页的数据 - * - * @param - * @param clazz - * @param flipper - * @param bean - * @return - */ - @Override - public Sheet querySheet(Class clazz, final Flipper flipper, final FilterBean bean) { - return querySheet(clazz, null, flipper, bean); - } - - @Override - public Sheet querySheet(Class clazz, final Flipper flipper, final FilterNode node) { - return querySheet(clazz, null, flipper, node); - } - - /** - * 根据过滤对象FilterBean和翻页对象Flipper查询一页的数据, 对象只填充或排除SelectField指定的字段 - * - * @param - * @param clazz - * @param selects - * @param flipper - * @param bean - * @return - */ - @Override - public Sheet querySheet(Class clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) { - return querySheet(true, true, clazz, selects, flipper, FilterNodeBean.createFilterNode(bean)); - } - - @Override - public Sheet querySheet(Class clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) { - return querySheet(true, true, clazz, selects, flipper, node); - } - - private Sheet querySheet(boolean readcache, boolean needtotal, Class clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) { - final EntityInfo info = loadEntityInfo(clazz); - final EntityCache cache = info.getCache(); - if (readcache && cache != null) { - if (node == null || node.isCacheUseable(this)) { - if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " cache query predicate = " + (node == null ? null : node.createPredicate(cache))); - Sheet sheet = cache.querySheet(needtotal, selects, flipper, node); - if (!sheet.isEmpty() || info.isVirtualEntity() || cache.isFullLoaded()) return sheet; - } - } - final Connection conn = createReadSQLConnection(); - try { - final SelectColumn sels = selects; - final List list = new ArrayList(); - final Map joinTabalis = node == null ? null : node.getJoinTabalis(); - final CharSequence join = node == null ? null : node.createSQLJoin(this, joinTabalis, info); - final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis); - final String sql = "SELECT a.* FROM " + info.getTable() + " a" + (join == null ? "" : join) - + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)) + info.createSQLOrderby(flipper); - if (debug.get() && info.isLoggable(Level.FINEST)) - logger.finest(clazz.getSimpleName() + " query sql=" + sql + (flipper == null ? "" : (" LIMIT " + flipper.index() + "," + flipper.getSize()))); - final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - final ResultSet set = ps.executeQuery(); - if (flipper != null && flipper.index() > 0) set.absolute(flipper.index()); - final int limit = flipper == null ? Integer.MAX_VALUE : flipper.getSize(); - int i = 0; - while (set.next()) { - i++; - list.add(info.getValue(sels, set)); - if (limit <= i) break; - } - long total = list.size(); - if (needtotal && flipper != null) { - set.last(); - total = set.getRow(); - } - set.close(); - ps.close(); - return new Sheet<>(total, list); - } catch (Exception ex) { - throw new RuntimeException(ex); - } finally { - closeSQLConnection(conn); - } - } -} diff --git a/src/com/wentch/redkale/source/DataSQLListener.java b/src/com/wentch/redkale/source/DataSQLListener.java deleted file mode 100644 index 5697176e2..000000000 --- a/src/com/wentch/redkale/source/DataSQLListener.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -/** - * @Resource(name = "property.datasource.nodeid") - * - * @author zhangjx - */ -public interface DataSQLListener { - - public void insert(String... sqls); - - public void update(String... sqls); - - public void delete(String... sqls); -} diff --git a/src/com/wentch/redkale/source/DataSource.java b/src/com/wentch/redkale/source/DataSource.java deleted file mode 100644 index 181d76a99..000000000 --- a/src/com/wentch/redkale/source/DataSource.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import com.wentch.redkale.util.*; -import java.io.*; -import java.util.*; - -/** - * - * @author zhangjx - */ -@SuppressWarnings("unchecked") -public interface DataSource { - - public static enum Reckon { - - AVG, COUNT, DISTINCTCOUNT, MAX, MIN, SUM; - - public String getColumn(String col) { - if (this == DISTINCTCOUNT) return "COUNT(DISTINCT " + col + ")"; - return this.name() + "(" + col + ")"; - } - } - - /** - * 创建读连接 - * - * @return - */ - public DataConnection createReadConnection(); - - /** - * 创建写连接 - * - * @return - */ - public DataConnection createWriteConnection(); - - //----------------------insert----------------------------- - /** - * 新增对象, 必须是Entity对象 - * - * @param - * @param values - */ - public void insert(T... values); - - public void insert(final DataConnection conn, T... values); - - /** - * 将entity的对象全部加载到Cache中去,如果clazz没有被@javax.persistence.Cacheable注解则不做任何事 - *

- * @param - * @param clazz - */ - public void refreshCache(Class clazz); - - //-------------------------delete-------------------------- - /** - * 删除对象, 必须是Entity对象 - * - * @param - * @param values - */ - public void delete(T... values); - - public void delete(final DataConnection conn, T... values); - - public void delete(Class clazz, Serializable... ids); - - public void delete(final DataConnection conn, Class clazz, Serializable... ids); - - public void delete(Class clazz, FilterNode node); - - public void delete(final DataConnection conn, Class clazz, FilterNode node); - - //------------------------update--------------------------- - /** - * 更新对象, 必须是Entity对象 - * - * @param - * @param values - */ - public void update(T... values); - - public void update(final DataConnection conn, T... values); - - public void updateColumn(Class clazz, Serializable id, String column, Serializable value); - - public void updateColumn(DataConnection conn, Class clazz, Serializable id, String column, Serializable value); - - public void updateColumns(final T value, final String... columns); - - public void updateColumns(final DataConnection conn, final T value, final String... columns); - - public void updateColumnIncrement(final Class clazz, Serializable id, String column, long incvalue); - - public void updateColumnIncrement(final DataConnection conn, Class clazz, Serializable id, String column, long incvalue); - - public void updateColumnAnd(final Class clazz, Serializable id, String column, long incvalue); - - public void updateColumnAnd(final DataConnection conn, Class clazz, Serializable id, String column, long incvalue); - - public void updateColumnOr(final Class clazz, Serializable id, String column, long incvalue); - - public void updateColumnOr(final DataConnection conn, Class clazz, Serializable id, String column, long incvalue); - - //-----------------------getXXXXResult----------------------------- - public Number getNumberResult(final Class entityClass, final Reckon reckon, final String column); - - public Number getNumberResult(final Class entityClass, final Reckon reckon, final String column, FilterBean bean); - - public Number getNumberResult(final Class entityClass, final Reckon reckon, final String column, FilterNode node); - - public Map getMapResult(Class entityClass, final String keyColumn, Reckon reckon, final String reckonColumn); - - public Map getMapResult(Class entityClass, final String keyColumn, Reckon reckon, final String reckonColumn, FilterBean bean); - - public Map getMapResult(Class entityClass, final String keyColumn, Reckon reckon, final String reckonColumn, FilterNode node); - - //-----------------------find---------------------------- - /** - * 根据主键获取对象 - * - * @param - * @param clazz - * @param pk - * @return - */ - public T find(Class clazz, Serializable pk); - - public T find(Class clazz, final SelectColumn selects, Serializable pk); - - public T findByColumn(Class clazz, String column, Serializable key); - - public T find(final Class clazz, final FilterNode node); - - public T find(final Class clazz, final FilterBean bean); - - public boolean exists(Class clazz, Serializable pk); - - public boolean exists(final Class clazz, final FilterNode node); - - public boolean exists(final Class clazz, final FilterBean bean); - - //-----------------------list set---------------------------- - /** - * 根据指定字段值查询对象某个字段的集合 - * - * @param - * @param - * @param selectedColumn - * @param clazz - * @param column - * @param key - * @return - */ - public HashSet queryColumnSet(String selectedColumn, Class clazz, String column, Serializable key); - - public HashSet queryColumnSet(String selectedColumn, Class clazz, FilterNode node); - - public HashSet queryColumnSet(String selectedColumn, Class clazz, FilterBean bean); - - public List queryColumnList(String selectedColumn, Class clazz, String column, Serializable key); - - public List queryColumnList(String selectedColumn, Class clazz, FilterNode node); - - public List queryColumnList(String selectedColumn, Class clazz, FilterBean bean); - - /** - * Map 接口 - *

- * @param - * @param - * @param clazz - * @param node - * @return - */ - public Map queryMap(final Class clazz, final FilterNode node); - - public Map queryMap(final Class clazz, final FilterBean bean); - - public Map queryMap(final Class clazz, final SelectColumn selects, final FilterNode node); - - public Map queryMap(final Class clazz, final SelectColumn selects, final FilterBean bean); - - /** - * 根据指定字段值查询对象集合 - * - * @param - * @param clazz - * @param column - * @param key - * @return - */ - public List queryList(final Class clazz, final String column, final Serializable key); - - public List queryList(final Class clazz, final FilterNode node); - - public List queryList(final Class clazz, final FilterBean bean); - - public List queryList(final Class clazz, final SelectColumn selects, final FilterNode node); - - public List queryList(final Class clazz, final SelectColumn selects, final FilterBean bean); - - public List queryList(final Class clazz, final Flipper flipper, final String column, final Serializable key); - - public List queryList(final Class clazz, final Flipper flipper, final FilterNode node); - - public List queryList(final Class clazz, final Flipper flipper, final FilterBean bean); - - public List queryList(final Class clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node); - - public List queryList(final Class clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean); - - //-----------------------sheet---------------------------- - /** - * 根据指定参数查询对象某个字段的集合 - *

- * @param - * @param - * @param selectedColumn - * @param clazz - * @param flipper - * @param bean - * @return - */ - public Sheet queryColumnSheet(final String selectedColumn, final Class clazz, final Flipper flipper, final FilterBean bean); - - public Sheet queryColumnSheet(final String selectedColumn, final Class clazz, final Flipper flipper, final FilterNode node); - - public Sheet querySheet(final Class clazz, final Flipper flipper, final FilterBean bean); - - public Sheet querySheet(final Class clazz, final Flipper flipper, final FilterNode node); - - public Sheet querySheet(final Class clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean); - - public Sheet querySheet(final Class clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node); - -} diff --git a/src/com/wentch/redkale/source/DistributeGenerator.java b/src/com/wentch/redkale/source/DistributeGenerator.java deleted file mode 100644 index d6421ed19..000000000 --- a/src/com/wentch/redkale/source/DistributeGenerator.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * - * @author zhangjx - */ -@Target({FIELD}) -@Retention(RUNTIME) -public @interface DistributeGenerator { - - /** - * 当使用DistributeGenerator控制主键值时, 如果表A删除的数据迁移到表B时, 就需要将表A的class标记: - * DistributeTables({B.class}) - * public class A { - * } - * 这样DistributeGenerator将从A、B表中取最大值来初始化主键值。 - * - * @author zhangjx - */ - @Target({TYPE}) - @Retention(RUNTIME) - public @interface DistributeTables { - - Class[] value(); - } - - long initialValue() default 1; - - /** - * 如果allocationSize的值小于或等于1,则主键不会加上nodeid - *

- * @return - */ - int allocationSize() default 1000; -} diff --git a/src/com/wentch/redkale/source/EntityCache.java b/src/com/wentch/redkale/source/EntityCache.java deleted file mode 100644 index 9c17e45b5..000000000 --- a/src/com/wentch/redkale/source/EntityCache.java +++ /dev/null @@ -1,654 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import java.io.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.function.*; -import java.util.logging.*; -import java.util.stream.Stream; -import javax.persistence.Transient; -import com.wentch.redkale.util.*; -import com.wentch.redkale.source.DataSource.Reckon; -import static com.wentch.redkale.source.DataSource.Reckon.*; -import java.util.stream.*; - -/** - * - * @author zhangjx - * @param - */ -public final class EntityCache { - - private static final Logger logger = Logger.getLogger(EntityCache.class.getName()); - - private final ConcurrentHashMap map = new ConcurrentHashMap(); - - private final Collection list = new ConcurrentLinkedQueue(); // CopyOnWriteArrayList 插入慢、查询快; 10w数据插入需要3.2秒; ConcurrentLinkedQueue 插入快、查询慢;10w数据查询需要 0.062秒, 查询慢40%; - - private final Map> sortComparators = new ConcurrentHashMap<>(); - - private final Class type; - - private final boolean needcopy; - - private final Creator creator; - - private final Attribute primary; - - private final Reproduce reproduce; - - private boolean fullloaded; - - final EntityInfo info; - - public EntityCache(final EntityInfo info) { - this.info = info; - this.type = info.getType(); - this.creator = info.getCreator(); - this.primary = info.primary; - this.needcopy = true; - this.reproduce = Reproduce.create(type, type, (m) -> { - try { - return type.getDeclaredField(m).getAnnotation(Transient.class) == null; - } catch (Exception e) { - return true; - } - }); - } - - public void fullLoad(List all) { - if (all == null) return; - clear(); - all.stream().filter(x -> x != null).forEach(x -> { - this.map.put(this.primary.get(x), x); - }); - this.list.addAll(all); - this.fullloaded = true; - } - - public Class getType() { - return type; - } - - public void clear() { - this.fullloaded = false; - this.list.clear(); - this.map.clear(); - } - - public boolean isFullLoaded() { - return fullloaded; - } - - public T find(Serializable id) { - if (id == null) return null; - T rs = map.get(id); - return rs == null ? null : (needcopy ? reproduce.copy(this.creator.create(), rs) : rs); - } - - public T find(final SelectColumn selects, final Serializable id) { - if (id == null) return null; - T rs = map.get(id); - if (rs == null) return null; - if (selects == null) return (needcopy ? reproduce.copy(this.creator.create(), rs) : rs); - T t = this.creator.create(); - for (Attribute attr : this.info.attributes) { - if (selects.test(attr.field())) attr.set(t, attr.get(rs)); - } - return t; - } - - public T find(final SelectColumn selects, FilterNode node) { - final Predicate filter = node == null ? null : node.createPredicate(this); - Stream stream = this.list.stream(); - if (filter != null) stream = stream.filter(filter); - Optional opt = stream.findFirst(); - if (!opt.isPresent()) return null; - if (selects == null) return (needcopy ? reproduce.copy(this.creator.create(), opt.get()) : opt.get()); - T rs = opt.get(); - T t = this.creator.create(); - for (Attribute attr : this.info.attributes) { - if (selects.test(attr.field())) attr.set(t, attr.get(rs)); - } - return t; - } - - public boolean exists(Serializable id) { - if (id == null) return false; - final Class atype = this.primary.type(); - if (id.getClass() != atype && id instanceof Number) { - if (atype == int.class || atype == Integer.class) { - id = ((Number) id).intValue(); - } else if (atype == long.class || atype == Long.class) { - id = ((Number) id).longValue(); - } else if (atype == short.class || atype == Short.class) { - id = ((Number) id).shortValue(); - } else if (atype == float.class || atype == Float.class) { - id = ((Number) id).floatValue(); - } else if (atype == byte.class || atype == Byte.class) { - id = ((Number) id).byteValue(); - } else if (atype == double.class || atype == Double.class) { - id = ((Number) id).doubleValue(); - } - } - return this.map.containsKey(id); - } - - public boolean exists(FilterNode node) { - final Predicate filter = node == null ? null : node.createPredicate(this); - Stream stream = this.list.stream(); - if (filter != null) stream = stream.filter(filter); - return stream.findFirst().isPresent(); - } - - public boolean exists(final Predicate filter) { - return (filter != null) && this.list.stream().filter(filter).findFirst().isPresent(); - } - - public Map getMapResult(final String keyColumn, final Reckon reckon, final String reckonColumn, FilterNode node) { - final Attribute keyAttr = info.getAttribute(keyColumn); - final Predicate filter = node == null ? null : node.createPredicate(this); - final Attribute reckonAttr = reckonColumn == null ? null : info.getAttribute(reckonColumn); - Stream stream = this.list.stream(); - if (filter != null) stream = stream.filter(filter); - Collector collector = null; - final Class valtype = reckonAttr == null ? null : reckonAttr.type(); - switch (reckon) { - case AVG: - if (valtype == float.class || valtype == Float.class || valtype == double.class || valtype == Double.class) { - collector = (Collector) Collectors.averagingDouble((T t) -> ((Number) reckonAttr.get(t)).doubleValue()); - } else { - collector = (Collector) Collectors.averagingLong((T t) -> ((Number) reckonAttr.get(t)).longValue()); - } - break; - case COUNT: collector = (Collector) Collectors.counting(); - break; - case DISTINCTCOUNT: - collector = (Collector) Collectors.mapping((t) -> reckonAttr.get(t), Collectors.toSet()); - break; - case MAX: - case MIN: - Comparator comp = (o1, o2) -> o1 == null ? (o2 == null ? 0 : -1) : ((Comparable) reckonAttr.get(o1)).compareTo(reckonAttr.get(o2)); - collector = (Collector) ((reckon == MAX) ? Collectors.maxBy(comp) : Collectors.minBy(comp)); - break; - case SUM: - if (valtype == float.class || valtype == Float.class || valtype == double.class || valtype == Double.class) { - collector = (Collector) Collectors.summingDouble((T t) -> ((Number) reckonAttr.get(t)).doubleValue()); - } else { - collector = (Collector) Collectors.summingLong((T t) -> ((Number) reckonAttr.get(t)).longValue()); - } - break; - } - Map rs = stream.collect(Collectors.groupingBy(t -> keyAttr.get(t), LinkedHashMap::new, collector)); - if (reckon == MAX || reckon == MIN) { - Map rs2 = new LinkedHashMap(); - rs.forEach((x, y) -> { - if (((Optional) y).isPresent()) rs2.put(x, reckonAttr.get((T) ((Optional) y).get())); - }); - rs = rs2; - } else if (reckon == DISTINCTCOUNT) { - Map rs2 = new LinkedHashMap(); - rs.forEach((x, y) -> rs2.put(x, ((Set) y).size())); - rs = rs2; - } - return rs; - } - - public Number getNumberResult(final Reckon reckon, final String column, FilterNode node) { - final Attribute attr = column == null ? null : info.getAttribute(column); - final Predicate filter = node == null ? null : node.createPredicate(this); - Stream stream = this.list.stream(); - if (filter != null) stream = stream.filter(filter); - switch (reckon) { - case AVG: - if (attr.type() == int.class || attr.type() == Integer.class) { - return (int) stream.mapToInt(x -> (Integer) attr.get(x)).average().orElse(0); - } else if (attr.type() == long.class || attr.type() == Long.class) { - return (long) stream.mapToLong(x -> (Long) attr.get(x)).average().orElse(0); - } else if (attr.type() == short.class || attr.type() == Short.class) { - return (short) stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).average().orElse(0); - } else if (attr.type() == float.class || attr.type() == Float.class) { - return (float) stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).average().orElse(0); - } else if (attr.type() == double.class || attr.type() == Double.class) { - return stream.mapToDouble(x -> (Double) attr.get(x)).average().orElse(0); - } - throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type()); - case COUNT: return stream.count(); - case DISTINCTCOUNT: return stream.map(x -> attr.get(x)).distinct().count(); - - case MAX: - if (attr.type() == int.class || attr.type() == Integer.class) { - return stream.mapToInt(x -> (Integer) attr.get(x)).max().orElse(0); - } else if (attr.type() == long.class || attr.type() == Long.class) { - return stream.mapToLong(x -> (Long) attr.get(x)).max().orElse(0); - } else if (attr.type() == short.class || attr.type() == Short.class) { - return (short) stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).max().orElse(0); - } else if (attr.type() == float.class || attr.type() == Float.class) { - return (float) stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).max().orElse(0); - } else if (attr.type() == double.class || attr.type() == Double.class) { - return stream.mapToDouble(x -> (Double) attr.get(x)).max().orElse(0); - } - throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type()); - - case MIN: - if (attr.type() == int.class || attr.type() == Integer.class) { - return stream.mapToInt(x -> (Integer) attr.get(x)).min().orElse(0); - } else if (attr.type() == long.class || attr.type() == Long.class) { - return stream.mapToLong(x -> (Long) attr.get(x)).min().orElse(0); - } else if (attr.type() == short.class || attr.type() == Short.class) { - return (short) stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).min().orElse(0); - } else if (attr.type() == float.class || attr.type() == Float.class) { - return (float) stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).min().orElse(0); - } else if (attr.type() == double.class || attr.type() == Double.class) { - return stream.mapToDouble(x -> (Double) attr.get(x)).min().orElse(0); - } - throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type()); - - case SUM: - if (attr.type() == int.class || attr.type() == Integer.class) { - return stream.mapToInt(x -> (Integer) attr.get(x)).sum(); - } else if (attr.type() == long.class || attr.type() == Long.class) { - return stream.mapToLong(x -> (Long) attr.get(x)).sum(); - } else if (attr.type() == short.class || attr.type() == Short.class) { - return (short) stream.mapToInt(x -> ((Short) attr.get(x)).intValue()).sum(); - } else if (attr.type() == float.class || attr.type() == Float.class) { - return (float) stream.mapToDouble(x -> ((Float) attr.get(x)).doubleValue()).sum(); - } else if (attr.type() == double.class || attr.type() == Double.class) { - return stream.mapToDouble(x -> (Double) attr.get(x)).sum(); - } - throw new RuntimeException("getNumberResult error(type:" + type + ", attr.declaringClass: " + attr.declaringClass() + ", attr.field: " + attr.field() + ", attr.type: " + attr.type()); - } - return -1; - } - - public Sheet querySheet(final SelectColumn selects, final Flipper flipper, final FilterNode node) { - return querySheet(true, selects, flipper, node); - } - - public Sheet querySheet(final boolean needtotal, final SelectColumn selects, final Flipper flipper, FilterNode node) { - final Predicate filter = node == null ? null : node.createPredicate(this); - final Comparator comparator = createComparator(flipper); - long total = 0; - if (needtotal) { - Stream stream = this.list.stream(); - if (filter != null) stream = stream.filter(filter); - total = stream.count(); - } - if (needtotal && total == 0) return new Sheet<>(); - Stream stream = this.list.stream(); - if (filter != null) stream = stream.filter(filter); - if (comparator != null) stream = stream.sorted(comparator); - if (flipper != null) stream = stream.skip(flipper.index()).limit(flipper.getSize()); - final List rs = new ArrayList<>(); - if (selects == null) { - Consumer action = x -> rs.add(needcopy ? reproduce.copy(creator.create(), x) : x); - if (comparator != null) { - stream.forEachOrdered(action); - } else { - stream.forEach(action); - } - } else { - final List> attrs = new ArrayList<>(); - info.forEachAttribute((k, v) -> { - if (selects.test(k)) attrs.add(v); - }); - Consumer action = x -> { - final T item = creator.create(); - for (Attribute attr : attrs) { - attr.set(item, attr.get(x)); - } - rs.add(item); - }; - if (comparator != null) { - stream.forEachOrdered(action); - } else { - stream.forEach(action); - } - } - if (!needtotal) total = rs.size(); - return new Sheet<>(total, rs); - } - - public void insert(T value) { - if (value == null) return; - final T rs = reproduce.copy(this.creator.create(), value); //确保同一主键值的map与list中的对象必须共用。 - T old = this.map.put(this.primary.get(rs), rs); - if (old == null) { - this.list.add(rs); - } else { - logger.log(Level.WARNING, "cache repeat insert data: " + value); - } - } - - public void delete(final Serializable id) { - if (id == null) return; - final T rs = this.map.remove(id); - if (rs != null) this.list.remove(rs); - } - - public Serializable[] delete(final FilterNode node) { - if (node == null || this.list.isEmpty()) return new Serializable[0]; - Object[] rms = this.list.stream().filter(node.createPredicate(this)).toArray(); - Serializable[] ids = new Serializable[rms.length]; - int i = -1; - for (Object o : rms) { - final T t = (T) o; - ids[++i] = this.primary.get(t); - this.map.remove(ids[i]); - this.list.remove(t); - } - return ids; - } - - public void update(final T value) { - if (value == null) return; - T rs = this.map.get(this.primary.get(value)); - if (rs == null) return; - this.reproduce.copy(rs, value); - } - - public T update(final T value, Collection> attrs) { - if (value == null) return value; - T rs = this.map.get(this.primary.get(value)); - if (rs == null) return rs; - for (Attribute attr : attrs) { - attr.set(rs, attr.get(value)); - } - return rs; - } - - public T update(final Serializable id, Attribute attr, final V fieldValue) { - if (id == null) return null; - T rs = this.map.get(id); - if (rs != null) attr.set(rs, fieldValue); - return rs; - } - - public T updateColumnOr(final Serializable id, Attribute attr, final long orvalue) { - if (id == null) return null; - T rs = this.map.get(id); - if (rs == null) return rs; - Number numb = (Number) attr.get(rs); - return updateColumnIncrAndOr(attr, rs, (numb == null) ? orvalue : (numb.longValue() | orvalue)); - } - - public T updateColumnAnd(final Serializable id, Attribute attr, final long andvalue) { - if (id == null) return null; - T rs = this.map.get(id); - if (rs == null) return rs; - Number numb = (Number) attr.get(rs); - return updateColumnIncrAndOr(attr, rs, (numb == null) ? 0 : (numb.longValue() & andvalue)); - } - - public T updateColumnIncrement(final Serializable id, Attribute attr, final long incvalue) { - if (id == null) return null; - T rs = this.map.get(id); - if (rs == null) return rs; - Number numb = (Number) attr.get(rs); - return updateColumnIncrAndOr(attr, rs, (numb == null) ? incvalue : (numb.longValue() + incvalue)); - } - - private T updateColumnIncrAndOr(Attribute attr, final T rs, Number numb) { - final Class ft = attr.type(); - if (ft == int.class || ft == Integer.class) { - numb = numb.intValue(); - } else if (ft == long.class || ft == Long.class) { - numb = numb.longValue(); - } else if (ft == short.class || ft == Short.class) { - numb = numb.shortValue(); - } else if (ft == float.class || ft == Float.class) { - numb = numb.floatValue(); - } else if (ft == double.class || ft == Double.class) { - numb = numb.doubleValue(); - } else if (ft == byte.class || ft == Byte.class) { - numb = numb.byteValue(); - } - attr.set(rs, (V) numb); - return rs; - } - - public Attribute getAttribute(String fieldname) { - return info.getAttribute(fieldname); - } - - //------------------------------------------------------------------------------------------------------------------------------- - protected Comparator createComparator(Flipper flipper) { - if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return null; - final String sort = flipper.getSort(); - Comparator comparator = this.sortComparators.get(sort); - if (comparator != null) return comparator; - for (String item : sort.split(",")) { - if (item.trim().isEmpty()) continue; - String[] sub = item.trim().split("\\s+"); - int pos = sub[0].indexOf('('); - Attribute attr; - if (pos <= 0) { - attr = getAttribute(sub[0]); - } else { //含SQL函数 - int pos2 = sub[0].lastIndexOf(')'); - final Attribute pattr = getAttribute(sub[0].substring(pos + 1, pos2)); - final String func = sub[0].substring(0, pos); - if ("ABS".equalsIgnoreCase(func)) { - if (pattr.type() == int.class || pattr.type() == Integer.class) { - attr = new Attribute() { - - @Override - public Class type() { - return pattr.type(); - } - - @Override - public Class declaringClass() { - return pattr.declaringClass(); - } - - @Override - public String field() { - return pattr.field(); - } - - @Override - public Serializable get(T obj) { - return Math.abs(((Number) pattr.get(obj)).intValue()); - } - - @Override - public void set(T obj, Serializable value) { - pattr.set(obj, value); - } - }; - } else if (pattr.type() == long.class || pattr.type() == Long.class) { - attr = new Attribute() { - - @Override - public Class type() { - return pattr.type(); - } - - @Override - public Class declaringClass() { - return pattr.declaringClass(); - } - - @Override - public String field() { - return pattr.field(); - } - - @Override - public Serializable get(T obj) { - return Math.abs(((Number) pattr.get(obj)).longValue()); - } - - @Override - public void set(T obj, Serializable value) { - pattr.set(obj, value); - } - }; - } else if (pattr.type() == float.class || pattr.type() == Float.class) { - attr = new Attribute() { - - @Override - public Class type() { - return pattr.type(); - } - - @Override - public Class declaringClass() { - return pattr.declaringClass(); - } - - @Override - public String field() { - return pattr.field(); - } - - @Override - public Serializable get(T obj) { - return Math.abs(((Number) pattr.get(obj)).floatValue()); - } - - @Override - public void set(T obj, Serializable value) { - pattr.set(obj, value); - } - }; - } else if (pattr.type() == double.class || pattr.type() == Double.class) { - attr = new Attribute() { - - @Override - public Class type() { - return pattr.type(); - } - - @Override - public Class declaringClass() { - return pattr.declaringClass(); - } - - @Override - public String field() { - return pattr.field(); - } - - @Override - public Serializable get(T obj) { - return Math.abs(((Number) pattr.get(obj)).doubleValue()); - } - - @Override - public void set(T obj, Serializable value) { - pattr.set(obj, value); - } - }; - } else { - throw new RuntimeException("Flipper not supported sort illegal type by ABS (" + flipper.getSort() + ")"); - } - } else if (func.isEmpty()) { - attr = pattr; - } else { - throw new RuntimeException("Flipper not supported sort illegal function (" + flipper.getSort() + ")"); - } - } - Comparator c = (sub.length > 1 && sub[1].equalsIgnoreCase("DESC")) ? (T o1, T o2) -> { - Comparable c1 = (Comparable) attr.get(o1); - Comparable c2 = (Comparable) attr.get(o2); - return c2 == null ? -1 : c2.compareTo(c1); - } : (T o1, T o2) -> { - Comparable c1 = (Comparable) attr.get(o1); - Comparable c2 = (Comparable) attr.get(o2); - return c1 == null ? -1 : c1.compareTo(c2); - }; - - if (comparator == null) { - comparator = c; - } else { - comparator = comparator.thenComparing(c); - } - } - this.sortComparators.put(sort, comparator); - return comparator; - } - - private static class UniqueSequence implements Serializable { - - private final Serializable[] value; - - public UniqueSequence(Serializable[] val) { - this.value = val; - } - - @Override - public int hashCode() { - return Arrays.deepHashCode(this.value); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - final UniqueSequence other = (UniqueSequence) obj; - if (value.length != other.value.length) return false; - for (int i = 0; i < value.length; i++) { - if (!value[i].equals(other.value[i])) return false; - } - return true; - } - - } - - private static interface UniqueAttribute extends Predicate { - - public Serializable getValue(T bean); - - @Override - public boolean test(FilterNode node); - - public static UniqueAttribute create(final Attribute[] attributes) { - if (attributes.length == 1) { - final Attribute attribute = attributes[0]; - return new UniqueAttribute() { - - @Override - public Serializable getValue(T bean) { - return attribute.get(bean); - } - - @Override - public boolean test(FilterNode node) { - if (node == null || node.isOr()) return false; - if (!attribute.field().equals(node.column)) return false; - if (node.nodes == null) return true; - for (FilterNode n : node.nodes) { - if (!test(n)) return false; - } - return true; - } - }; - } else { - return new UniqueAttribute() { - - @Override - public Serializable getValue(T bean) { - final Serializable[] rs = new Serializable[attributes.length]; - for (int i = 0; i < rs.length; i++) { - rs[i] = attributes[i].get(bean); - } - return new UniqueSequence(rs); - } - - @Override - public boolean test(FilterNode node) { - return true; - } - }; - } - } - } - -} diff --git a/src/com/wentch/redkale/source/EntityInfo.java b/src/com/wentch/redkale/source/EntityInfo.java deleted file mode 100644 index 0af5ccf87..000000000 --- a/src/com/wentch/redkale/source/EntityInfo.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import com.sun.istack.internal.logging.Logger; -import com.wentch.redkale.util.*; -import java.io.Serializable; -import java.lang.reflect.*; -import java.sql.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.function.*; -import java.util.logging.*; -import javax.persistence.*; - -/** - * - * @author zhangjx - * @param - */ -@SuppressWarnings("unchecked") -public final class EntityInfo { - - private static final ConcurrentHashMap entityInfos = new ConcurrentHashMap<>(); - - private static final Logger logger = Logger.getLogger(EntityInfo.class); - - //Entity类的类名 - private final Class type; - - //类对应的数据表名, 如果是VirtualEntity 类, 则该字段为null - private final String table; - - private final Creator creator; - - //主键 - final Attribute primary; - - private final EntityCache cache; - - //key是field的name, 不是sql字段。 - //存放所有与数据库对应的字段, 包括主键 - private final HashMap> attributeMap = new HashMap<>(); - - final Attribute[] attributes; - - //key是field的name, value是Column的别名,即数据库表的字段名 - //只有field.name 与 Column.name不同才存放在aliasmap里. - private final Map aliasmap; - - private final Map> updateAttributeMap = new HashMap<>(); - - final String querySQL; - - private final Attribute[] queryAttributes; //数据库中所有字段 - - final String insertSQL; - - final Attribute[] insertAttributes; //数据库中所有可新增字段 - - final String updateSQL; - - final Attribute[] updateAttributes; //数据库中所有可更新字段 - - final String deleteSQL; - - private final int logLevel; - - private final Map sortOrderbySqls = new ConcurrentHashMap<>(); - - //---------------------计算主键值---------------------------- - private final int nodeid; - - final Class[] distributeTables; - - final boolean autoGenerated; - - final boolean distributed; - - boolean initedPrimaryValue = false; - - final AtomicLong primaryValue = new AtomicLong(0); - - final int allocationSize; - //------------------------------------------------------------ - - public static EntityInfo load(Class clazz, final int nodeid, final boolean cacheForbidden, - Function fullloader) { - EntityInfo rs = entityInfos.get(clazz); - if (rs != null) return rs; - synchronized (entityInfos) { - rs = entityInfos.get(clazz); - if (rs == null) { - if (nodeid < 0) throw new IllegalArgumentException("nodeid(" + nodeid + ") is illegal"); - rs = new EntityInfo(clazz, nodeid, cacheForbidden); - entityInfos.put(clazz, rs); - AutoLoad auto = clazz.getAnnotation(AutoLoad.class); - if (rs.cache != null && auto != null && auto.value()) { - if (fullloader == null) throw new IllegalArgumentException(clazz.getName() + " auto loader is illegal"); - rs.cache.fullLoad(fullloader.apply(clazz)); - } - } - return rs; - } - } - - static EntityInfo get(Class clazz) { - return entityInfos.get(clazz); - } - - private EntityInfo(Class type, int nodeid, final boolean cacheForbidden) { - this.type = type; - //--------------------------------------------- - this.nodeid = nodeid >= 0 ? nodeid : 0; - DistributeGenerator.DistributeTables dt = type.getAnnotation(DistributeGenerator.DistributeTables.class); - this.distributeTables = dt == null ? null : dt.value(); - - LogLevel ll = type.getAnnotation(LogLevel.class); - this.logLevel = ll == null ? Integer.MIN_VALUE : Level.parse(ll.value()).intValue(); - //--------------------------------------------- - Table t = type.getAnnotation(Table.class); - if (type.getAnnotation(VirtualEntity.class) != null) { - this.table = null; - } else { - this.table = (t == null) ? type.getSimpleName().toLowerCase() : (t.catalog().isEmpty()) ? t.name() : (t.catalog() + '.' + t.name()); - } - this.creator = Creator.create(type); - Attribute idAttr0 = null; - Map aliasmap0 = null; - Class cltmp = type; - Set fields = new HashSet<>(); - List> queryattrs = new ArrayList<>(); - List insertcols = new ArrayList<>(); - List> insertattrs = new ArrayList<>(); - List updatecols = new ArrayList<>(); - List> updateattrs = new ArrayList<>(); - boolean auto = false; - boolean sqldistribute = false; - int allocationSize0 = 0; - - do { - for (Field field : cltmp.getDeclaredFields()) { - if (Modifier.isStatic(field.getModifiers())) continue; - if (Modifier.isFinal(field.getModifiers())) continue; - if (field.getAnnotation(Transient.class) != null) continue; - if (fields.contains(field.getName())) continue; - final String fieldname = field.getName(); - final Column col = field.getAnnotation(Column.class); - final String sqlfield = col == null || col.name().isEmpty() ? fieldname : col.name(); - if (!fieldname.equals(sqlfield)) { - if (aliasmap0 == null) aliasmap0 = new HashMap<>(); - aliasmap0.put(fieldname, sqlfield); - } - Attribute attr; - try { - attr = Attribute.create(cltmp, field); - } catch (RuntimeException e) { - continue; - } - if (field.getAnnotation(javax.persistence.Id.class) != null && idAttr0 == null) { - idAttr0 = attr; - GeneratedValue gv = field.getAnnotation(GeneratedValue.class); - auto = gv != null; - if (gv != null && gv.strategy() != GenerationType.IDENTITY) { - throw new RuntimeException(cltmp.getName() + "'s @ID primary not a GenerationType.IDENTITY"); - } - DistributeGenerator dg = field.getAnnotation(DistributeGenerator.class); - if (dg != null) { - if (!field.getType().isPrimitive()) throw new RuntimeException(cltmp.getName() + "'s @DistributeGenerator primary must be primitive class type field"); - sqldistribute = true; - auto = false; - allocationSize0 = dg.allocationSize(); - primaryValue.set(dg.initialValue()); - } - if (!auto) { - insertcols.add(sqlfield); - insertattrs.add(attr); - } - } else { - if (col == null || col.insertable()) { - insertcols.add(sqlfield); - insertattrs.add(attr); - } - if (col == null || col.updatable()) { - updatecols.add(sqlfield); - updateattrs.add(attr); - updateAttributeMap.put(fieldname, attr); - } - } - queryattrs.add(attr); - fields.add(fieldname); - attributeMap.put(fieldname, attr); - } - } while ((cltmp = cltmp.getSuperclass()) != Object.class); - this.primary = idAttr0; - this.aliasmap = aliasmap0; - this.attributes = attributeMap.values().toArray(new Attribute[attributeMap.size()]); - this.queryAttributes = queryattrs.toArray(new Attribute[queryattrs.size()]); - this.insertAttributes = insertattrs.toArray(new Attribute[insertattrs.size()]); - this.updateAttributes = updateattrs.toArray(new Attribute[updateattrs.size()]); - if (table != null) { - StringBuilder insertsb = new StringBuilder(); - StringBuilder insertsb2 = new StringBuilder(); - for (String col : insertcols) { - if (insertsb.length() > 0) insertsb.append(','); - insertsb.append(col); - if (insertsb2.length() > 0) insertsb2.append(','); - insertsb2.append('?'); - } - this.insertSQL = "INSERT INTO " + table + "(" + insertsb + ") VALUES(" + insertsb2 + ")"; - StringBuilder updatesb = new StringBuilder(); - for (String col : updatecols) { - if (updatesb.length() > 0) updatesb.append(','); - updatesb.append(col).append(" = ?"); - } - this.updateSQL = "UPDATE " + table + " SET " + updatesb + " WHERE " + getPrimarySQLColumn(null) + " = ?"; - this.deleteSQL = "DELETE FROM " + table + " WHERE " + getPrimarySQLColumn(null) + " = ?"; - this.querySQL = "SELECT * FROM " + table + " WHERE " + getPrimarySQLColumn(null) + " = ?"; - } else { - this.insertSQL = null; - this.updateSQL = null; - this.deleteSQL = null; - this.querySQL = null; - } - this.autoGenerated = auto; - this.distributed = sqldistribute; - this.allocationSize = allocationSize0; - //----------------cache-------------- - Cacheable c = type.getAnnotation(Cacheable.class); - if (this.table == null || (!cacheForbidden && c != null && c.value())) { - this.cache = new EntityCache<>(this); - } else { - this.cache = null; - } - } - - public void createPrimaryValue(T src) { - long v = allocationSize > 1 ? (primaryValue.incrementAndGet() * allocationSize + nodeid) : primaryValue.incrementAndGet(); - if (primary.type() == int.class || primary.type() == Integer.class) { - getPrimary().set(src, (Integer) ((Long) v).intValue()); - } else { - getPrimary().set(src, v); - } - } - - public EntityCache getCache() { - return cache; - } - - public boolean isCacheFullLoaded() { - return cache != null && cache.isFullLoaded(); - } - - public Creator getCreator() { - return creator; - } - - public Class getType() { - return type; - } - - /** - * 是否虚拟类 - *

- * @return - */ - public boolean isVirtualEntity() { - return table == null; - } - - public String getTable() { - return table; - } - - public Attribute getPrimary() { - return this.primary; - } - - public void forEachAttribute(BiConsumer> action) { - this.attributeMap.forEach(action); - } - - public Attribute getAttribute(String fieldname) { - if (fieldname == null) return null; - return this.attributeMap.get(fieldname); - } - - public Attribute getUpdateAttribute(String fieldname) { - return this.updateAttributeMap.get(fieldname); - } - - public boolean isNoAlias() { - return this.aliasmap == null; - } - - protected String createSQLOrderby(Flipper flipper) { - if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return ""; - final String sort = flipper.getSort(); - String sql = this.sortOrderbySqls.get(sort); - if (sql != null) return sql; - final StringBuilder sb = new StringBuilder(); - sb.append(" ORDER BY "); - if (isNoAlias()) { - sb.append(sort); - } else { - boolean flag = false; - for (String item : sort.split(",")) { - if (item.isEmpty()) continue; - String[] sub = item.split("\\s+"); - if (flag) sb.append(','); - if (sub.length < 2 || sub[1].equalsIgnoreCase("ASC")) { - sb.append(getSQLColumn("a", sub[0])).append(" ASC"); - } else { - sb.append(getSQLColumn("a", sub[0])).append(" DESC"); - } - flag = true; - } - } - sql = sb.toString(); - this.sortOrderbySqls.put(sort, sql); - return sql; - } - - //根据field字段名获取数据库对应的字段名 - public String getSQLColumn(String tabalis, String fieldname) { - return this.aliasmap == null ? (tabalis == null ? fieldname : (tabalis + '.' + fieldname)) - : (tabalis == null ? aliasmap.getOrDefault(fieldname, fieldname) : (tabalis + '.' + aliasmap.getOrDefault(fieldname, fieldname))); - } - - public String getPrimarySQLColumn() { - return getSQLColumn(null, this.primary.field()); - } - - //数据库字段名 - public String getPrimarySQLColumn(String tabalis) { - return getSQLColumn(tabalis, this.primary.field()); - } - - protected Map> getAttributes() { - return attributeMap; - } - - public boolean isLoggable(Level l) { - return l.intValue() >= this.logLevel; - } - - protected T getValue(final SelectColumn sels, final ResultSet set) throws SQLException { - T obj = creator.create(); - for (Attribute attr : queryAttributes) { - if (sels == null || sels.test(attr.field())) { - Serializable o = (Serializable) set.getObject(this.getSQLColumn(null, attr.field())); - if (o != null) { - Class t = attr.type(); - if (t == short.class) { - o = ((Number) o).shortValue(); - } else if (t == long.class) { - o = ((Number) o).longValue(); - } else if (t == int.class) { - o = ((Number) o).intValue(); - } - } - attr.set(obj, o); - } - } - return obj; - } -} diff --git a/src/com/wentch/redkale/source/FilterBean.java b/src/com/wentch/redkale/source/FilterBean.java deleted file mode 100644 index cb525fb4d..000000000 --- a/src/com/wentch/redkale/source/FilterBean.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - -package com.wentch.redkale.source; - -/** - * - * @author zhangjx - */ -public interface FilterBean { - -} diff --git a/src/com/wentch/redkale/source/FilterColumn.java b/src/com/wentch/redkale/source/FilterColumn.java deleted file mode 100644 index 9d3441ff6..000000000 --- a/src/com/wentch/redkale/source/FilterColumn.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({FIELD}) -@Retention(RUNTIME) -public @interface FilterColumn { - - /** - * 对应Entity Class中字段的名称, 而不是SQL字段名称 - * - * @return - */ - String name() default ""; - - /** - * 当字段类型是Number时, 如果值>=least() 则需要过滤, 否则跳过该字段 - * - * @return - */ - long least() default 1; - - /** - * express的默认值根据字段类型的不同而不同: - * 数组 --> IN - * Range --> Between - * 其他 --> = - * - * @return - */ - FilterExpress express() default FilterExpress.EQUAL; - -} diff --git a/src/com/wentch/redkale/source/FilterExpress.java b/src/com/wentch/redkale/source/FilterExpress.java deleted file mode 100644 index 7f680eb90..000000000 --- a/src/com/wentch/redkale/source/FilterExpress.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -/** - * - * @author zhangjx - */ -public enum FilterExpress { - - EQUAL("="), - NOTEQUAL("<>"), - GREATERTHAN(">"), - LESSTHAN("<"), - GREATERTHANOREQUALTO(">="), - LESSTHANOREQUALTO("<="), - LIKE("LIKE"), - NOTLIKE("NOT LIKE"), - IGNORECASELIKE("LIKE"), //不区分大小写的 LIKE - IGNORECASENOTLIKE("NOT LIKE"), //不区分大小写的 NOT LIKE - BETWEEN("BETWEEN"), - NOTBETWEEN("NOT BETWEEN"), - IN("IN"), - NOTIN("NOT IN"), - ISNULL("IS NULL"), - ISNOTNULL("IS NOT NULL"), - OPAND("&"), //与运算 > 0 - OPOR("|"), //或运算 > 0 - OPANDNO("&"), //与运算 == 0 - AND("AND"), - OR("OR"); - - private final String value; - - private FilterExpress(String v) { - this.value = v; - } - - public String value() { - return value; - } - -} diff --git a/src/com/wentch/redkale/source/FilterGroup.java b/src/com/wentch/redkale/source/FilterGroup.java deleted file mode 100644 index 1c0929c1e..000000000 --- a/src/com/wentch/redkale/source/FilterGroup.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static java.lang.annotation.ElementType.FIELD; -import java.lang.annotation.*; - -/* - * 默认情况下FilterBean下的过滤字段之间是AND关系。 - * 当需要使用OR或AND OR组合过滤查询时需要使用 FilterGroup。 - * FilterGroup 的value 必须是[OR]或者[AND]开头, 多级需要用点.分隔。 (注: 暂时不支持多级) - * 示例一: - * public class TestFilterBean implements FilterBean { - * - * private int id; - * - * @FilterGroup("[OR]g1") - * private String desc; - * - * @FilterGroup("[OR]g1") - * private String name; - * } - * 转换的SQL语句为: WHERE id = ? AND (desc = ? OR name = ?) - * - * 示例二: - * public class TestFilterBean implements FilterBean { - * - * private int id; - * - * @FilterGroup("[OR]g1.[AND]subg1") - * @FilterColumn(express = LIKE) - * private String desc; - * - * @FilterGroup("[OR]g1.[AND]subg1") - * @FilterColumn(express = LIKE) - * private String name; - * - * @FilterGroup("[OR]g1.[OR]subg2") - * private int age; - * - * @FilterGroup("[OR]g1.[OR]subg2") - * private int birthday; - * } - * 转换的SQL语句为: WHERE id = ? AND ((desc LIKE ? AND name LIKE ?) OR (age = ? OR birthday = ?)) - * 因为默认是AND关系, @FilterGroup("") 等价于 @FilterGroup("[AND]") - * 所以示例二的@FilterGroup("[OR]g1.[AND]subg1") 可以简化为 @FilterGroup("[OR]g1") - */ -/** - * @author zhangjx - */ -@Inherited -@Documented -@Target({FIELD}) -@Retention(RUNTIME) -public @interface FilterGroup { - - String value() default "[AND]"; -} diff --git a/src/com/wentch/redkale/source/FilterGroups.java b/src/com/wentch/redkale/source/FilterGroups.java deleted file mode 100644 index 722710b75..000000000 --- a/src/com/wentch/redkale/source/FilterGroups.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.*; - -/** - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({FIELD}) -@Retention(RUNTIME) -public @interface FilterGroups { - - FilterGroup[] value(); -} diff --git a/src/com/wentch/redkale/source/FilterJoinColumn.java b/src/com/wentch/redkale/source/FilterJoinColumn.java deleted file mode 100644 index 2bdef114a..000000000 --- a/src/com/wentch/redkale/source/FilterJoinColumn.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({FIELD}) -@Retention(RUNTIME) -public @interface FilterJoinColumn { - - /** - * 关联表 通常join表默认别名为b/c/d/...自增, 被join表默认别名为a - * - * @return - */ - Class table(); - - /** - * - * 单个关联字段, 默认使用join表(b)的主键, join表与被join表(a)的字段必须一样 - * 例如: SELECT a.* FROM user a INNER JOIN record b ON a.userid = b.userid - * 那么注解为: @FilterJoinColumn(table = Record.class, column = "userid") - *

- * @deprecated 使用columns 代替 - * - * @return - */ - String column() default ""; - - /** - * - * 多个关联字段, 默认使用join表(b)的主键, join表与被join表(a)的字段必须一样 - * 例如: SELECT a.* FROM user a INNER JOIN record b ON a.userid = b.userid AND a.usertype = b.usertype - * 那么注解为: @FilterJoinColumn(table = Record.class, columns = {"userid", "usertype"}) - *

- * @return - */ - String[] columns() default {}; -} diff --git a/src/com/wentch/redkale/source/FilterJoinNode.java b/src/com/wentch/redkale/source/FilterJoinNode.java deleted file mode 100644 index 98951f0fd..000000000 --- a/src/com/wentch/redkale/source/FilterJoinNode.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import com.wentch.redkale.util.*; -import java.io.*; -import java.util.*; -import java.util.concurrent.atomic.*; -import java.util.function.*; - -/** - * - * @author zhangjx - */ -public class FilterJoinNode extends FilterNode { - - private Class joinClass; - - private EntityInfo joinEntity; //在调用 createSQLJoin 和 isCacheUseable 时会注入 - - private String[] joinColumns; - - public FilterJoinNode() { - } - - protected FilterJoinNode(Class joinClass, String[] joinColumns, String column, Serializable value) { - this(joinClass, joinColumns, column, null, value); - } - - protected FilterJoinNode(Class joinClass, String[] joinColumns, String column, FilterExpress express, Serializable value) { - Objects.requireNonNull(joinClass); - Objects.requireNonNull(joinColumns); - this.joinClass = joinClass; - this.joinColumns = joinColumns; - this.column = column; - this.express = express; - this.value = value; - } - - protected FilterJoinNode(FilterJoinNode node) { - this(node.joinClass, node.joinColumns, node.column, node.express, node.value); - this.joinEntity = node.joinEntity; - this.or = node.or; - this.nodes = node.nodes; - } - - public static FilterJoinNode create(Class joinClass, String joinColumn, String column, Serializable value) { - return new FilterJoinNode(joinClass, new String[]{joinColumn}, column, value); - } - - public static FilterJoinNode create(Class joinClass, String joinColumn, String column, FilterExpress express, Serializable value) { - return new FilterJoinNode(joinClass, new String[]{joinColumn}, column, express, value); - } - - public static FilterJoinNode create(Class joinClass, String[] joinColumns, String column, Serializable value) { - return new FilterJoinNode(joinClass, joinColumns, column, value); - } - - public static FilterJoinNode create(Class joinClass, String[] joinColumns, String column, FilterExpress express, Serializable value) { - return new FilterJoinNode(joinClass, joinColumns, column, express, value); - } - - @Override - protected FilterNode any(final FilterNode node0, boolean signor) { - Objects.requireNonNull(node0); - if (!(node0 instanceof FilterJoinNode)) { - throw new IllegalArgumentException(this + (signor ? " or " : " and ") + " a node but " + String.valueOf(node0) + "is not a " + FilterJoinNode.class.getSimpleName()); - } - final FilterJoinNode node = (FilterJoinNode) node0; - if (this.nodes == null) { - this.nodes = new FilterNode[]{node}; - this.or = signor; - return this; - } - if (or == signor || this.column == null) { - FilterNode[] newsiblings = new FilterNode[nodes.length + 1]; - System.arraycopy(nodes, 0, newsiblings, 0, nodes.length); - newsiblings[nodes.length] = node; - this.nodes = newsiblings; - if (this.column == null) this.or = signor; - return this; - } - this.nodes = new FilterNode[]{new FilterJoinNode(node), node}; - this.column = null; - this.express = null; - this.value = null; - this.joinClass = null; - this.joinEntity = null; - this.joinColumns = null; - this.or = signor; - return this; - } - - @Override - protected CharSequence createSQLExpress(final EntityInfo info, final Map joinTabalis) { - return super.createSQLExpress(this.joinEntity == null ? info : this.joinEntity, joinTabalis); - } - - @Override - protected Predicate createPredicate(final EntityCache cache) { - if (column == null && this.nodes == null) return null; - final EntityCache joinCache = this.joinEntity.getCache(); - final AtomicBoolean more = new AtomicBoolean(); - Predicate filter = createJoinPredicate(more); - Predicate rs = null; - if (filter == null && !more.get()) return rs; - if (filter != null) { - final Predicate inner = filter; - rs = new Predicate() { - - @Override - public boolean test(final T t) { - Predicate joinPredicate = null; - for (String joinColumn : joinColumns) { - final Serializable key = cache.getAttribute(joinColumn).get(t); - final Attribute joinAttr = joinCache.getAttribute(joinColumn); - Predicate p = (E e) -> key.equals(joinAttr.get(e)); - joinPredicate = joinPredicate == null ? p : joinPredicate.and(p); - } - return joinCache.exists(inner.and(joinPredicate)); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(" #-- ON ").append(joinColumns[0]).append("=").append(joinClass == null ? "null" : joinClass.getSimpleName()).append(".").append(joinColumns[0]); - for (int i = 1; i < joinColumns.length; i++) { - sb.append(" AND ").append(joinColumns[i]).append("=").append(joinClass == null ? "null" : joinClass.getSimpleName()).append(".").append(joinColumns[i]); - } - sb.append(" --# ").append(inner.toString()); - return sb.toString(); - } - }; - } - if (more.get()) { //存在不同Class的关联表 - if (this.nodes != null) { - for (FilterNode node : this.nodes) { - if (((FilterJoinNode) node).joinClass == this.joinClass) continue; - Predicate f = node.createPredicate(cache); - if (f == null) continue; - final Predicate one = rs; - final Predicate two = f; - rs = (rs == null) ? f : (or ? new Predicate() { - - @Override - public boolean test(T t) { - return one.test(t) || two.test(t); - } - - @Override - public String toString() { - return "(" + one + " OR " + two + ")"; - } - } : new Predicate() { - - @Override - public boolean test(T t) { - return one.test(t) && two.test(t); - } - - @Override - public String toString() { - return "(" + one + " AND " + two + ")"; - } - }); - } - } - } - return rs; - } - - private Predicate createJoinPredicate(final AtomicBoolean more) { - if (column == null && this.nodes == null) return null; - final EntityCache joinCache = this.joinEntity.getCache(); - Predicate filter = createElementPredicate(joinCache, true); - if (this.nodes != null) { - for (FilterNode node : this.nodes) { - if (((FilterJoinNode) node).joinClass != this.joinClass) { - more.set(true); - continue; - } - Predicate f = ((FilterJoinNode) node).createJoinPredicate(more); - if (f == null) continue; - final Predicate one = filter; - final Predicate two = f; - filter = (filter == null) ? f : (or ? new Predicate() { - - @Override - public boolean test(E t) { - return one.test(t) || two.test(t); - } - - @Override - public String toString() { - return "(" + one + " OR " + two + ")"; - } - } : new Predicate() { - - @Override - public boolean test(E t) { - return one.test(t) && two.test(t); - } - - @Override - public String toString() { - return "(" + one + " AND " + two + ")"; - } - }); - } - } - return filter; - } - - @Override - protected CharSequence createSQLJoin(final Function func, final Map joinTabalis, final EntityInfo info) { - boolean morejoin = false; - if (this.joinEntity == null) { - if (this.joinClass != null) this.joinEntity = func.apply(this.joinClass); - if (this.nodes != null) { - for (FilterNode node : this.nodes) { - if (node instanceof FilterJoinNode) { - FilterJoinNode joinNode = ((FilterJoinNode) node); - if (joinNode.joinClass != null) { - joinNode.joinEntity = func.apply(joinNode.joinClass); - if (this.joinClass != null && this.joinClass != joinNode.joinClass) morejoin = true; - } - } - } - } - } - StringBuilder sb = new StringBuilder(); - if (this.joinClass != null) { - sb.append(createElementSQLJoin(joinTabalis, info, this)); - } - if (morejoin) { - Set set = new HashSet<>(); - if (this.joinClass != null) set.add(this.joinClass); - for (FilterNode node : this.nodes) { - if (node instanceof FilterJoinNode) { - FilterJoinNode joinNode = ((FilterJoinNode) node); - if (!set.contains(joinNode.joinClass)) { - CharSequence cs = createElementSQLJoin(joinTabalis, info, joinNode); - if (cs != null) { - sb.append(cs); - set.add(joinNode.joinClass); - } - } - } - } - } - return sb; - } - - private static CharSequence createElementSQLJoin(final Map joinTabalis, final EntityInfo info, final FilterJoinNode node) { - if (node.joinClass == null) return null; - StringBuilder sb = new StringBuilder(); - String[] joinColumns = node.joinColumns; - sb.append(" INNER JOIN ").append(node.joinEntity.getTable()).append(" ").append(joinTabalis.get(node.joinClass)) - .append(" ON ").append(info.getSQLColumn("a", joinColumns[0])).append(" = ").append(node.joinEntity.getSQLColumn(joinTabalis.get(node.joinClass), joinColumns[0])); - for (int i = 1; i < joinColumns.length; i++) { - sb.append(" AND ").append(info.getSQLColumn("a", joinColumns[i])).append(" = ").append(node.joinEntity.getSQLColumn(joinTabalis.get(node.joinClass), joinColumns[i])); - } - return sb; - } - - @Override - protected boolean isCacheUseable(final Function entityApplyer) { - if (this.joinEntity == null) this.joinEntity = entityApplyer.apply(this.joinClass); - if (!this.joinEntity.isCacheFullLoaded()) return false; - if (this.nodes == null) return true; - for (FilterNode node : this.nodes) { - if (!node.isCacheUseable(entityApplyer)) return false; - } - return true; - } - - @Override - protected void putJoinTabalis(Map map) { - if (this.joinClass != null && !map.containsKey(this.joinClass)) map.put(joinClass, String.valueOf((char) ('b' + map.size()))); - if (this.nodes == null) return; - for (FilterNode node : this.nodes) { - node.putJoinTabalis(map); - } - } - - @Override - protected final boolean isjoin() { - return true; - } - - @Override - public String toString() { - return toString(joinClass == null ? null : joinClass.getSimpleName()).toString(); - } - - public Class getJoinClass() { - return joinClass; - } - - public void setJoinClass(Class joinClass) { - this.joinClass = joinClass; - } - - public String[] getJoinColumns() { - return joinColumns; - } - - public void setJoinColumns(String[] joinColumns) { - this.joinColumns = joinColumns; - } - -} diff --git a/src/com/wentch/redkale/source/FilterNode.java b/src/com/wentch/redkale/source/FilterNode.java deleted file mode 100644 index 9b61a11eb..000000000 --- a/src/com/wentch/redkale/source/FilterNode.java +++ /dev/null @@ -1,958 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import static com.wentch.redkale.source.FilterExpress.*; -import com.wentch.redkale.util.*; -import java.io.*; -import java.lang.reflect.*; -import java.util.*; -import java.util.function.*; - -/** - * 注意: - * 在调用 createSQLExpress 之前必须先调用 createSQLJoin - * 在调用 createPredicate 之前必须先调用 isCacheUseable - * - * @author zhangjx - */ -public class FilterNode { - - protected String column; - - protected FilterExpress express; - - protected Serializable value; - - //---------------------------------------------- - protected boolean or; - - protected FilterNode[] nodes; - - public FilterNode() { - } - - protected FilterNode(String col, FilterExpress exp, Serializable val) { - Objects.requireNonNull(col); - if (exp == null) { - if (val instanceof Range) { - exp = FilterExpress.BETWEEN; - } else if (val instanceof Collection) { - exp = FilterExpress.IN; - } else if (val != null && val.getClass().isArray()) { - exp = FilterExpress.IN; - } else { - exp = FilterExpress.EQUAL; - } - } - this.column = col; - this.express = exp; - this.value = val; - } - - public final FilterNode and(FilterNode node) { - return any(node, false); - } - - public final FilterNode and(String column, Serializable value) { - return and(column, null, value); - } - - public final FilterNode and(String column, FilterExpress express, Serializable value) { - return and(new FilterNode(column, express, value)); - } - - public final FilterNode or(FilterNode node) { - return any(node, true); - } - - public final FilterNode or(String column, Serializable value) { - return or(column, null, value); - } - - public final FilterNode or(String column, FilterExpress express, Serializable value) { - return or(new FilterNode(column, express, value)); - } - - protected FilterNode any(FilterNode node, boolean signor) { - Objects.requireNonNull(node); - if (this.column == null) { - this.column = node.column; - this.express = node.express; - this.value = node.value; - return this; - } - if (this.nodes == null) { - this.nodes = new FilterNode[]{node}; - this.or = signor; - return this; - } - if (or == signor) { - FilterNode[] newsiblings = new FilterNode[nodes.length + 1]; - System.arraycopy(nodes, 0, newsiblings, 0, nodes.length); - newsiblings[nodes.length] = node; - this.nodes = newsiblings; - return this; - } - FilterNode newnode = new FilterNode(this.column, this.express, this.value); - newnode.or = this.or; - newnode.nodes = this.nodes; - this.nodes = new FilterNode[]{newnode, node}; - this.column = null; - this.express = null; - this.or = signor; - this.value = null; - return this; - } - - /** - * 该方法需要重载 - * - * @param - * @param func - * @param joinTabalis - * @param info - * @return - */ - protected CharSequence createSQLJoin(final Function func, final Map joinTabalis, final EntityInfo info) { - if (joinTabalis == null || this.nodes == null) return null; - StringBuilder sb = null; - for (FilterNode node : this.nodes) { - CharSequence cs = node.createSQLJoin(func, joinTabalis, info); - if (cs == null) continue; - if (sb == null) sb = new StringBuilder(); - sb.append(cs); - } - return sb; - } - - /** - * 该方法需要重载 - * - * @return - */ - protected boolean isjoin() { - if (this.nodes == null) return false; - for (FilterNode node : this.nodes) { - if (node.isjoin()) return true; - } - return false; - } - - protected final Map getJoinTabalis() { - if (!isjoin()) return null; - Map map = new HashMap<>(); - putJoinTabalis(map); - return map; - } - - protected void putJoinTabalis(Map map) { - if (this.nodes == null) return; - for (FilterNode node : this.nodes) { - node.putJoinTabalis(map); - } - } - - /** - * 该方法需要重载 - * - * @param entityApplyer - * @return - */ - protected boolean isCacheUseable(final Function entityApplyer) { - if (this.nodes == null) return true; - for (FilterNode node : this.nodes) { - if (!node.isCacheUseable(entityApplyer)) return false; - } - return true; - } - - /** - * 该方法需要重载 - * - * @param - * @param joinTabalis - * @param info - * @return - */ - protected CharSequence createSQLExpress(final EntityInfo info, final Map joinTabalis) { - CharSequence sb0 = this.column == null || info == null ? null : createElementSQLExpress(info, joinTabalis == null ? null : joinTabalis.get(info.getType())); - if (this.nodes == null) return sb0; - final StringBuilder rs = new StringBuilder(); - rs.append('('); - boolean more = false; - if (sb0 != null && sb0.length() > 2) { - more = true; - rs.append(sb0); - } - for (FilterNode node : this.nodes) { - CharSequence f = node.createSQLExpress(info, joinTabalis); - if (f == null || f.length() < 3) continue; - if (more) rs.append(or ? " OR " : " AND "); - rs.append(f); - more = true; - } - rs.append(')'); - if (rs.length() < 5) return null; - return rs; - } - - public static FilterNode create(String column, Serializable value) { - return create(column, null, value); - } - - public static FilterNode create(String column, FilterExpress express, Serializable value) { - return new FilterNode(column, express, value); - } - - protected final CharSequence createElementSQLExpress(final EntityInfo info, String talis) { - if (column == null) return null; - if (talis == null) talis = "a"; - if (express == ISNULL || express == ISNOTNULL) { - return new StringBuilder().append(info.getSQLColumn(talis, column)).append(' ').append(express.value()); - } - final CharSequence val = formatToString(express, getValue()); - if (val == null) return null; - StringBuilder sb = new StringBuilder(32); - if (express == IGNORECASELIKE || express == IGNORECASENOTLIKE) { - sb.append("LOWER(").append(info.getSQLColumn(talis, column)).append(')'); - } else { - sb.append(info.getSQLColumn(talis, column)); - } - sb.append(' '); - switch (express) { - case OPAND: - case OPOR: - sb.append(express.value()).append(' ').append(val).append(" > 0"); - break; - case OPANDNO: - sb.append(express.value()).append(' ').append(val).append(" = 0"); - break; - default: - sb.append(express.value()).append(' ').append(val); - break; - } - return sb; - } - - protected Predicate createPredicate(final EntityCache cache) { - if (cache == null || (column == null && this.nodes == null)) return null; - Predicate filter = createElementPredicate(cache, false); - if (this.nodes == null) return filter; - for (FilterNode node : this.nodes) { - Predicate f = node.createPredicate(cache); - if (f == null) continue; - final Predicate one = filter; - final Predicate two = f; - filter = (filter == null) ? f : (or ? new Predicate() { - - @Override - public boolean test(T t) { - return one.test(t) || two.test(t); - } - - @Override - public String toString() { - return "(" + one + " OR " + two + ")"; - } - } : new Predicate() { - - @Override - public boolean test(T t) { - return one.test(t) && two.test(t); - } - - @Override - public String toString() { - return "(" + one + " AND " + two + ")"; - } - }); - } - return filter; - } - - protected final Predicate createElementPredicate(final EntityCache cache, final boolean join) { - if (column == null) return null; - return createElementPredicate(cache, join, cache.getAttribute(column)); - } - - protected final Predicate createElementPredicate(final EntityCache cache, final boolean join, final Attribute attr) { - if (attr == null) return null; - final String field = join ? (cache.getType().getSimpleName() + "." + attr.field()) : attr.field(); - if (express == ISNULL) return new Predicate() { - - @Override - public boolean test(T t) { - return attr.get(t) == null; - } - - @Override - public String toString() { - return field + " = null"; - } - }; - if (express == ISNOTNULL) return new Predicate() { - - @Override - public boolean test(T t) { - return attr.get(t) != null; - } - - @Override - public String toString() { - return field + " != null"; - } - }; - if (attr == null) return null; - Serializable val0 = getValue(); - if (val0 == null) return null; - - final Class atype = attr.type(); - final Class valtype = val0.getClass(); - if (atype != valtype && val0 instanceof Number) { - if (atype == int.class || atype == Integer.class) { - val0 = ((Number) val0).intValue(); - } else if (atype == long.class || atype == Long.class) { - val0 = ((Number) val0).longValue(); - } else if (atype == short.class || atype == Short.class) { - val0 = ((Number) val0).shortValue(); - } else if (atype == float.class || atype == Float.class) { - val0 = ((Number) val0).floatValue(); - } else if (atype == byte.class || atype == Byte.class) { - val0 = ((Number) val0).byteValue(); - } else if (atype == double.class || atype == Double.class) { - val0 = ((Number) val0).doubleValue(); - } - } else if (valtype.isArray()) { - final int len = Array.getLength(val0); - if (len == 0 && express == NOTIN) return null; - final Class compType = valtype.getComponentType(); - if (atype != compType && len > 0) { - if (!compType.isPrimitive() && Number.class.isAssignableFrom(compType)) throw new RuntimeException("param(" + val0 + ") type not match " + atype + " for column " + column); - if (atype == int.class || atype == Integer.class) { - int[] vs = new int[len]; - for (int i = 0; i < len; i++) { - vs[i] = ((Number) Array.get(val0, i)).intValue(); - } - val0 = vs; - } else if (atype == long.class || atype == Long.class) { - long[] vs = new long[len]; - for (int i = 0; i < len; i++) { - vs[i] = ((Number) Array.get(val0, i)).longValue(); - } - val0 = vs; - } else if (atype == short.class || atype == Short.class) { - short[] vs = new short[len]; - for (int i = 0; i < len; i++) { - vs[i] = ((Number) Array.get(val0, i)).shortValue(); - } - val0 = vs; - } else if (atype == float.class || atype == Float.class) { - float[] vs = new float[len]; - for (int i = 0; i < len; i++) { - vs[i] = ((Number) Array.get(val0, i)).floatValue(); - } - val0 = vs; - } else if (atype == byte.class || atype == Byte.class) { - byte[] vs = new byte[len]; - for (int i = 0; i < len; i++) { - vs[i] = ((Number) Array.get(val0, i)).byteValue(); - } - val0 = vs; - } else if (atype == double.class || atype == Double.class) { - double[] vs = new double[len]; - for (int i = 0; i < len; i++) { - vs[i] = ((Number) Array.get(val0, i)).doubleValue(); - } - val0 = vs; - } - } - } else if (val0 instanceof Collection) { - final Collection collection = (Collection) val0; - if (collection.isEmpty() && express == NOTIN) return null; - if (!collection.isEmpty()) { - Iterator it = collection.iterator(); - it.hasNext(); - Class fs = it.next().getClass(); - Class pfs = fs; - if (fs == Integer.class) { - pfs = int.class; - } else if (fs == Long.class) { - pfs = long.class; - } else if (fs == Short.class) { - pfs = short.class; - } else if (fs == Float.class) { - pfs = float.class; - } else if (fs == Byte.class) { - pfs = byte.class; - } else if (fs == Double.class) { - pfs = double.class; - } - if (Number.class.isAssignableFrom(fs) && atype != fs && atype != pfs) { //需要转换 - ArrayList list = new ArrayList(collection.size()); - if (atype == int.class || atype == Integer.class) { - for (Number num : (Collection) collection) { - list.add(num.intValue()); - } - } else if (atype == long.class || atype == Long.class) { - for (Number num : (Collection) collection) { - list.add(num.longValue()); - } - } else if (atype == short.class || atype == Short.class) { - for (Number num : (Collection) collection) { - list.add(num.shortValue()); - } - } else if (atype == float.class || atype == Float.class) { - for (Number num : (Collection) collection) { - list.add(num.floatValue()); - } - } else if (atype == byte.class || atype == Byte.class) { - for (Number num : (Collection) collection) { - list.add(num.byteValue()); - } - } else if (atype == double.class || atype == Double.class) { - for (Number num : (Collection) collection) { - list.add(num.doubleValue()); - } - } - val0 = list; - } - } - } - final Serializable val = val0; - switch (express) { - case EQUAL: return new Predicate() { - - @Override - public boolean test(T t) { - return val.equals(attr.get(t)); - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + formatToString(val); - } - }; - case NOTEQUAL: return new Predicate() { - - @Override - public boolean test(T t) { - return !val.equals(attr.get(t)); - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + formatToString(val); - } - }; - case GREATERTHAN: return new Predicate() { - - @Override - public boolean test(T t) { - return ((Number) attr.get(t)).longValue() > ((Number) val).longValue(); - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + val; - } - }; - case LESSTHAN: return new Predicate() { - - @Override - public boolean test(T t) { - return ((Number) attr.get(t)).longValue() < ((Number) val).longValue(); - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + val; - } - }; - case GREATERTHANOREQUALTO: return new Predicate() { - - @Override - public boolean test(T t) { - return ((Number) attr.get(t)).longValue() >= ((Number) val).longValue(); - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + val; - } - }; - case LESSTHANOREQUALTO: return new Predicate() { - - @Override - public boolean test(T t) { - return ((Number) attr.get(t)).longValue() <= ((Number) val).longValue(); - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + val; - } - }; - - case OPAND: return new Predicate() { - - @Override - public boolean test(T t) { - return (((Number) attr.get(t)).longValue() & ((Number) val).longValue()) > 0; - } - - @Override - public String toString() { - return field + " & " + val + " > 0"; - } - }; - case OPOR: return new Predicate() { - - @Override - public boolean test(T t) { - return (((Number) attr.get(t)).longValue() | ((Number) val).longValue()) > 0; - } - - @Override - public String toString() { - return field + " | " + val + " > 0"; - } - }; - case OPANDNO: return new Predicate() { - - @Override - public boolean test(T t) { - return (((Number) attr.get(t)).longValue() & ((Number) val).longValue()) == 0; - } - - @Override - public String toString() { - return field + " & " + val + " = 0"; - } - }; - case LIKE: - return new Predicate() { - - @Override - public boolean test(T t) { - Object rs = attr.get(t); - return rs != null && rs.toString().contains(val.toString()); - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + formatToString(val); - } - }; - case IGNORECASELIKE: - final String valstr = val.toString().toLowerCase(); - return new Predicate() { - - @Override - public boolean test(T t) { - Object rs = attr.get(t); - return rs != null && rs.toString().toLowerCase().contains(valstr); - } - - @Override - public String toString() { - return "LOWER(" + field + ") " + express.value() + ' ' + formatToString(valstr); - } - }; - case NOTLIKE: - return new Predicate() { - - @Override - public boolean test(T t) { - Object rs = attr.get(t); - return rs == null || !rs.toString().contains(val.toString()); - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + formatToString(val); - } - }; - case IGNORECASENOTLIKE: - final String valstr2 = val.toString().toLowerCase(); - return new Predicate() { - - @Override - public boolean test(T t) { - Object rs = attr.get(t); - return rs == null || !rs.toString().toLowerCase().contains(valstr2); - } - - @Override - public String toString() { - return "LOWER(" + field + ") " + express.value() + ' ' + formatToString(valstr2); - } - }; - case BETWEEN: - case NOTBETWEEN: - Range range = (Range) val; - final Comparable min = range.getMin(); - final Comparable max = range.getMax(); - if (express == BETWEEN) return new Predicate() { - - @Override - public boolean test(T t) { - Comparable rs = (Comparable) attr.get(t); - if (rs == null) return false; - if (min != null && min.compareTo(rs) >= 0) return false; - return !(max != null && max.compareTo(rs) <= 0); - } - - @Override - public String toString() { - return field + " BETWEEN " + min + " AND " + max; - } - }; - if (express == NOTBETWEEN) return new Predicate() { - - @Override - public boolean test(T t) { - Comparable rs = (Comparable) attr.get(t); - if (rs == null) return true; - if (min != null && min.compareTo(rs) >= 0) return true; - return (max != null && max.compareTo(rs) <= 0); - } - - @Override - public String toString() { - return field + " NOT BETWEEN " + min + " AND " + max; - } - }; - return null; - case IN: - case NOTIN: - Predicate filter; - if (val instanceof Collection) { - Collection array = (Collection) val; - if (array.isEmpty()) { //express 只会是 IN - filter = new Predicate() { - - @Override - public boolean test(T t) { - return false; - } - - @Override - public String toString() { - return field + ' ' + express.value() + " []"; - } - }; - } else { - filter = new Predicate() { - - @Override - public boolean test(T t) { - Object rs = attr.get(t); - return rs != null && array.contains(rs); - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + val; - } - }; - } - } else { - Class type = val.getClass(); - if (Array.getLength(val) == 0) {//express 只会是 IN - filter = new Predicate() { - - @Override - public boolean test(T t) { - return false; - } - - @Override - public String toString() { - return field + ' ' + express.value() + " []"; - } - }; - } else if (type == int[].class) { - filter = new Predicate() { - - @Override - public boolean test(T t) { - Object rs = attr.get(t); - if (rs == null) return false; - int k = (int) rs; - for (int v : (int[]) val) { - if (v == k) return true; - } - return false; - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + Arrays.toString((int[]) val); - } - }; - } else if (type == short[].class) { - filter = new Predicate() { - - @Override - public boolean test(T t) { - Object rs = attr.get(t); - if (rs == null) return false; - short k = (short) rs; - for (short v : (short[]) val) { - if (v == k) return true; - } - return false; - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + Arrays.toString((short[]) val); - } - }; - } else if (type == long[].class) { - filter = new Predicate() { - - @Override - public boolean test(T t) { - Object rs = attr.get(t); - if (rs == null) return false; - long k = (long) rs; - for (long v : (long[]) val) { - if (v == k) return true; - } - return false; - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + Arrays.toString((long[]) val); - } - }; - } else if (type == float[].class) { - filter = new Predicate() { - - @Override - public boolean test(T t) { - Object rs = attr.get(t); - if (rs == null) return false; - float k = (float) rs; - for (float v : (float[]) val) { - if (v == k) return true; - } - return false; - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + Arrays.toString((float[]) val); - } - }; - } else if (type == double[].class) { - filter = new Predicate() { - - @Override - public boolean test(T t) { - Object rs = attr.get(t); - if (rs == null) return false; - double k = (double) rs; - for (double v : (double[]) val) { - if (v == k) return true; - } - return false; - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + Arrays.toString((double[]) val); - } - }; - } else { - filter = new Predicate() { - - @Override - public boolean test(T t) { - Object rs = attr.get(t); - if (rs == null) return false; - for (Object v : (Object[]) val) { - if (rs.equals(v)) return true; - } - return false; - } - - @Override - public String toString() { - return field + ' ' + express.value() + ' ' + Arrays.toString((Object[]) val); - } - }; - } - } - if (express == NOTIN) { - final Predicate filter2 = filter; - filter = new Predicate() { - - @Override - public boolean test(T t) { - return !filter2.test(t); - } - - @Override - public String toString() { - return filter2.toString(); - } - }; - } - return filter; - } - return null; - } - - @Override - public String toString() { - return toString(null).toString(); - } - - protected StringBuilder toString(final String prefix) { - StringBuilder sb = new StringBuilder(); - StringBuilder element = toElementString(prefix); - boolean more = element.length() > 0 && this.nodes != null; - if (more) sb.append('('); - sb.append(element); - if (this.nodes != null) { - for (FilterNode node : this.nodes) { - String s = node.toString(); - if (s.length() < 1) continue; - if (sb.length() > 1) sb.append(or ? " OR " : " AND "); - sb.append(s); - } - } - if (more) sb.append(')'); - return sb; - } - - protected final StringBuilder toElementString(final String prefix) { - StringBuilder sb = new StringBuilder(); - if (column != null) { - String col = prefix == null ? column : (prefix + "." + column); - Serializable ev = getValue(); - if (express == ISNULL || express == ISNOTNULL) { - sb.append(col).append(' ').append(express.value()); - } else if (ev != null) { - sb.append((express == IGNORECASELIKE || express == IGNORECASENOTLIKE) ? ("LOWER(" + col + ')') : col).append(' ').append(express.value()).append(' ').append(formatToString(express, ev)); - } - } - return sb; - } - - protected static CharSequence formatToString(Object value) { - CharSequence sb = formatToString(null, value); - return sb == null ? null : sb.toString(); - } - - private static CharSequence formatToString(FilterExpress express, Object value) { - if (value == null) return null; - if (value instanceof Number) return String.valueOf(value); - if (value instanceof CharSequence) { - if (express == LIKE || express == NOTLIKE) { - value = "%" + value + '%'; - } else if (express == IGNORECASELIKE || express == IGNORECASENOTLIKE) { - value = "%" + value.toString().toLowerCase() + '%'; - } - return new StringBuilder().append('\'').append(value.toString().replace("'", "\\'")).append('\''); - } else if (value instanceof Range) { - Range range = (Range) value; - boolean rangestring = range.getClass() == Range.StringRange.class; - StringBuilder sb = new StringBuilder(); - if (rangestring) { - sb.append('\'').append(range.getMin().toString().replace("'", "\\'")).append('\''); - } else { - sb.append(range.getMin()); - } - sb.append(" AND "); - if (rangestring) { - sb.append('\'').append(range.getMax().toString().replace("'", "\\'")).append('\''); - } else { - sb.append(range.getMax()); - } - return sb; - } else if (value.getClass().isArray()) { - int len = Array.getLength(value); - if (len == 0) return express == NOTIN ? null : new StringBuilder("(NULL)"); - if (len == 1) { - Object firstval = Array.get(value, 0); - if (firstval != null && firstval.getClass().isArray()) return formatToString(express, firstval); - } - StringBuilder sb = new StringBuilder(); - sb.append('('); - for (int i = 0; i < len; i++) { - Object o = Array.get(value, i); - if (sb.length() > 1) sb.append(','); - if (o instanceof CharSequence) { - sb.append('\'').append(o.toString().replace("'", "\\'")).append('\''); - } else { - sb.append(o); - } - } - return sb.append(')'); - } else if (value instanceof Collection) { - Collection c = (Collection) value; - if (c.isEmpty()) return express == NOTIN ? null : new StringBuilder("(NULL)"); - StringBuilder sb = new StringBuilder(); - sb.append('('); - for (Object o : c) { - if (sb.length() > 1) sb.append(','); - if (o instanceof CharSequence) { - sb.append('\'').append(o.toString().replace("'", "\\'")).append('\''); - } else { - sb.append(o); - } - } - return sb.append(')'); - } - return String.valueOf(value); - } - - public final Serializable getValue() { - return value; - } - - public final void setValue(Serializable value) { - this.value = value; - } - - public final boolean isOr() { - return or; - } - - public final void setOr(boolean or) { - this.or = or; - } - - public final String getColumn() { - return column; - } - - public final void setColumn(String column) { - this.column = column; - } - - public final FilterExpress getExpress() { - return express; - } - - public final void setExpress(FilterExpress express) { - this.express = express; - } - - public final FilterNode[] getNodes() { - return nodes; - } - - public final void setNodes(FilterNode[] nodes) { - this.nodes = nodes; - } - -} diff --git a/src/com/wentch/redkale/source/FilterNodeBean.java b/src/com/wentch/redkale/source/FilterNodeBean.java deleted file mode 100644 index 6d321b341..000000000 --- a/src/com/wentch/redkale/source/FilterNodeBean.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import static com.wentch.redkale.source.FilterExpress.*; -import com.wentch.redkale.util.*; -import java.io.*; -import java.lang.reflect.*; -import java.util.*; -import java.util.concurrent.*; -import javax.persistence.*; - -/** - * - * @author zhangjx - */ -public final class FilterNodeBean implements Comparable> { - - private static final ConcurrentHashMap beanodes = new ConcurrentHashMap<>(); - - private Attribute beanAttr; - - private String column; - - private FilterExpress express; - - private boolean or; - - private FilterNodeBean[] nodeBeans; - - //-----------------join table-------------------------- - private Class joinClass; - - private String[] joinColumns; - - //---------------------------------------------------- - private long least; - - private boolean string; - - private boolean number; - - public FilterNodeBean(FilterNodeBean bean) { - this.beanAttr = bean.beanAttr; - this.column = bean.column; - this.express = bean.express; - this.joinClass = bean.joinClass; - this.joinColumns = bean.joinColumns; - this.least = bean.least; - this.string = bean.string; - this.number = bean.number; - this.or = bean.or; - this.nodeBeans = bean.nodeBeans; - } - - private FilterNodeBean(final FilterJoinColumn joinCol, final FilterColumn filterCol, final Attribute attr) { - this.beanAttr = attr; - this.joinClass = joinCol == null ? null : joinCol.table(); - this.joinColumns = joinCol == null ? null : (joinCol.columns().length == 0 ? new String[]{joinCol.column()} : joinCol.columns()); - - final Class type = attr.type(); - this.column = (filterCol != null && !filterCol.name().isEmpty()) ? filterCol.name() : attr.field(); - - FilterExpress exp = filterCol == null ? null : filterCol.express(); - if (type.isArray() || Collection.class.isAssignableFrom(type)) { - if (Range.class.isAssignableFrom(type.getComponentType())) { - if (AND != exp) exp = OR; - } else if (NOTIN != exp) exp = IN; - } else if (Range.class.isAssignableFrom(type)) { - if (NOTBETWEEN != exp) exp = BETWEEN; - } - if (exp == null) exp = EQUAL; - this.express = exp; - - this.least = filterCol == null ? 1 : filterCol.least(); - this.number = (type.isPrimitive() && type != boolean.class) || Number.class.isAssignableFrom(type); - this.string = CharSequence.class.isAssignableFrom(type); - } - - private FilterNodeBean or(FilterNodeBean node) { - return any(node, true); - } - - private FilterNodeBean and(FilterNodeBean node) { - return any(node, false); - } - - private FilterNodeBean any(FilterNodeBean node, boolean signor) { - Objects.requireNonNull(node); - if (this.column == null) { - this.beanAttr = node.beanAttr; - this.column = node.column; - this.express = node.express; - this.joinClass = node.joinClass; - this.joinColumns = node.joinColumns; - this.least = node.least; - this.string = node.string; - this.number = node.number; - return this; - } - if (this.nodeBeans == null) { - this.nodeBeans = new FilterNodeBean[]{node}; - this.or = signor; - return this; - } - if (or == signor) { - FilterNodeBean[] newsiblings = new FilterNodeBean[nodeBeans.length + 1]; - System.arraycopy(nodeBeans, 0, newsiblings, 0, nodeBeans.length); - newsiblings[nodeBeans.length] = node; - this.nodeBeans = newsiblings; - return this; - } - this.nodeBeans = new FilterNodeBean[]{new FilterNodeBean(this), node}; - this.column = null; - this.or = signor; - return this; - } - - public static FilterNode createFilterNode(final FilterBean bean) { - if (bean == null) return null; - return load(bean.getClass()).create(bean); - } - - private FilterNode create(final T bean) { - if (bean == null) return null; - FilterNode node = null; - final Serializable val = beanAttr.get(bean); - if (column != null && val != null) { - boolean skip = false; - if (string && ((CharSequence) val).length() == 0) { - skip = true; - } else if (number && ((Number) val).longValue() < least) { - skip = true; - } - if (!skip) { - if (this.joinClass == null) { - node = FilterNode.create(column, express, val); - } else { - node = FilterJoinNode.create(joinClass, joinColumns, column, express, val); - } - } - } - if (this.nodeBeans == null) return node; - for (final FilterNodeBean fnb : this.nodeBeans) { - FilterNode n = fnb.create(bean); - if (n == null) continue; - node = node == null ? n : ((!(n instanceof FilterJoinNode)) ? n.any(node, or) : node.any(n, or)); - } - return node; - } - - private static FilterNodeBean createFilterNodeBean(final Class clazz) { - final Set fields = new HashSet<>(); - final Map nodemap = new LinkedHashMap(); - Class cltmp = clazz; - do { - for (final Field field : cltmp.getDeclaredFields()) { - if (Modifier.isStatic(field.getModifiers())) continue; - if (fields.contains(field.getName())) continue; - if (field.getAnnotation(Ignore.class) != null) continue; - if (field.getAnnotation(Transient.class) != null) continue; - - final boolean pubmod = Modifier.isPublic(field.getModifiers()); - - char[] chars = field.getName().toCharArray(); - chars[0] = Character.toUpperCase(chars[0]); - final Class t = field.getType(); - Method getter = null; - try { - getter = cltmp.getMethod(((t == boolean.class || t == Boolean.class) ? "is" : "get") + new String(chars)); - } catch (Exception ex) { - if (!pubmod) continue; - } - fields.add(field.getName()); - - final Attribute beanAttr = pubmod ? Attribute.create(field) : Attribute.create(getter, null); - FilterNodeBean nodeBean = new FilterNodeBean(field.getAnnotation(FilterJoinColumn.class), field.getAnnotation(FilterColumn.class), beanAttr); - - //------------------------------------ - { - FilterGroup[] refs = field.getAnnotationsByType(FilterGroup.class); - String[] groups = new String[refs.length]; - for (int i = 0; i < refs.length; i++) { - groups[i] = refs[i].value(); - } - if (groups.length == 0) groups = new String[]{"[AND]"}; - for (String key : groups) { - if (!key.startsWith("[AND]") && !key.startsWith("[OR]")) { - throw new RuntimeException(field + "'s FilterGroup.value(" + key + ") illegal, must be [AND] or [OR] startsWith"); - } - FilterNodeBean node = nodemap.get(key); - if (node == null) { - nodemap.put(key, nodeBean); - } else if (nodeBean.joinClass == null && node.joinClass != null) { //非joinNode 关联 joinNode - nodemap.put(key, nodeBean.any(node, key.substring(key.lastIndexOf('.') + 1).contains("[OR]"))); - } else { - node.any(nodeBean, key.substring(key.lastIndexOf('.') + 1).contains("[OR]")); - } - } - } - } - } while ((cltmp = cltmp.getSuperclass()) != Object.class); - final Map linkes = new LinkedHashMap<>(); - nodemap.forEach((k, v) -> { - String[] keys = k.split("\\."); - LinkNode link = linkes.get(keys[0]); - if (link == null) { - linkes.put(keys[0], new LinkNode(k, v)); - } else { - link.put(keys, 0, v); - } - }); - FilterNodeBean rs = null; - for (LinkNode link : linkes.values()) { - FilterNodeBean f = link.createFilterNodeBean(); - if (f == null) continue; - rs = rs == null ? f : rs.and(f); - } - if (rs.nodeBeans != null) Arrays.sort(rs.nodeBeans); - return rs; - } - - @Override - public int compareTo(FilterNodeBean o) { - if (this.joinClass == null && o.joinClass == null) return 0; - if (this.joinClass != null && o.joinClass != null) return 0; - return this.joinClass == null ? -1 : 1; - } - - private static class LinkNode { - - public final boolean or; - - public final String key; - - public final List beans = new ArrayList<>(); - - public final Map nexts = new LinkedHashMap<>(); - - public LinkNode(String keyString, FilterNodeBean node) { - String[] keys = keyString.split("\\."); - this.key = keys[0]; - this.or = this.key.contains("[OR]"); - put(keys, 0, node); - } - - public LinkNode(String[] keyStrings, int pos, FilterNodeBean node) { - this.key = keyStrings[pos]; - this.or = this.key.contains("[OR]"); - put(keyStrings, pos, node); - } - - public FilterNodeBean createFilterNodeBean() { - FilterNodeBean node = null; - for (FilterNodeBean bean : beans) { - node = node == null ? bean : node.any(bean, or); - } - for (LinkNode link : nexts.values()) { - FilterNodeBean f = link.createFilterNodeBean(); - if (f == null) continue; - node = node == null ? f : node.any(f, or); - } - return node; - } - - public final void put(final String[] keys, int pos, final FilterNodeBean node) { - if (keys.length == pos + 1 && this.key.equals(keys[pos])) { - this.beans.add(node); - return; - } - LinkNode link = nexts.get(keys[pos + 1]); - if (link == null) { - nexts.put(keys[pos + 1], new LinkNode(keys, pos + 1, node)); - } else { - link.put(keys, pos + 1, node); - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("{key = '").append(key).append("', or = ").append(or); - if (!beans.isEmpty()) { - sb.append(", beans = [\r\n"); - for (FilterNodeBean bean : this.beans) { - sb.append(" ").append(bean).append("\r\n"); - } - sb.append("]"); - } - if (!nexts.isEmpty()) { - sb.append(", nexts = [\r\n"); - for (LinkNode link : this.nexts.values()) { - sb.append(" ").append(link).append("\r\n"); - } - sb.append("]"); - } - sb.append("}"); - return sb.toString(); - } - } - - private static FilterNodeBean load(Class clazz) { - FilterNodeBean rs = beanodes.get(clazz); - if (rs != null) return rs; - synchronized (beanodes) { - rs = beanodes.get(clazz); - if (rs == null) { - rs = createFilterNodeBean(clazz); - beanodes.put(clazz, rs); - } - return rs; - } - } - - @Override - public String toString() { - return toString(joinClass == null ? null : joinClass.getSimpleName()).toString(); - } - - protected StringBuilder toString(final String prefix) { - StringBuilder sb = new StringBuilder(); - StringBuilder element = toElementString(prefix); - boolean more = element.length() > 0 && this.nodeBeans != null; - if (more) sb.append('('); - sb.append(element); - if (this.nodeBeans != null) { - for (FilterNodeBean node : this.nodeBeans) { - String s = node.toString(); - if (s.length() < 1) continue; - if (sb.length() > 1) sb.append(or ? " OR " : " AND "); - sb.append(s); - } - } - if (more) sb.append(')'); - return sb; - } - - protected final StringBuilder toElementString(final String prefix) { - StringBuilder sb = new StringBuilder(); - if (column != null) { - String col = prefix == null ? column : (prefix + "." + column); - if (express == ISNULL || express == ISNOTNULL) { - sb.append(col).append(' ').append(express.value()); - } else { - sb.append((express == IGNORECASELIKE || express == IGNORECASENOTLIKE) ? ("LOWER(" + col + ')') : col).append(' ').append(express.value()).append(" ?"); - } - } - return sb; - } -} diff --git a/src/com/wentch/redkale/source/Flipper.java b/src/com/wentch/redkale/source/Flipper.java deleted file mode 100644 index 4224cb815..000000000 --- a/src/com/wentch/redkale/source/Flipper.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import java.io.Serializable; - -/** - * - * @author zhangjx - */ -public final class Flipper implements Serializable { - - public static int DEFAULT_PAGESIZE = 20; - - private int size = DEFAULT_PAGESIZE; - - private int page = 1; - - private String sort = ""; - - public Flipper() { - } - - public Flipper(int pageSize) { - this.size = pageSize; - } - - public Flipper(String sortColumn) { - this.sort = sortColumn; - } - - public Flipper(int pageSize, int pageNo) { - this.size = pageSize; - this.page = pageNo; - } - - public Flipper(int pageSize, int pageNo, String sortColumn) { - this.size = pageSize; - this.page = pageNo; - this.sort = sortColumn; - } - - public void copyTo(Flipper copy) { - if (copy == null) return; - copy.page = this.page; - copy.size = this.size; - copy.sort = this.sort; - } - - public void copyFrom(Flipper copy) { - if (copy == null) return; - this.page = copy.page; - this.size = copy.size; - this.sort = copy.sort; - } - - public Flipper next() { - this.page++; - return this; - } - - public int index() { - return (getPage() - 1) * getSize(); - } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "{page:" + this.page + ", size=" + this.size + ", sort=" + this.sort + "}"; - } - - public int getSize() { - return size; - } - - public void setSize(int size) { - if (size > 0) { - this.size = size; - } - } - - public int getPage() { - return page; - } - - public void setPage(int page) { - if (page >= 0) { - this.page = page; - } - } - - public String getSort() { - return sort; - } - - public Flipper putSortIfEmpty(String sort) { - if (this.sort == null || this.sort.isEmpty()) { - this.sort = sort; - } - return this; - } - - public void setSort(String sort) { - if (sort != null) { - this.sort = sort.trim(); - } - } - -} diff --git a/src/com/wentch/redkale/source/JDBCPoolSource.java b/src/com/wentch/redkale/source/JDBCPoolSource.java deleted file mode 100644 index 51fb3e938..000000000 --- a/src/com/wentch/redkale/source/JDBCPoolSource.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import static com.wentch.redkale.source.DataDefaultSource.*; -import java.io.*; -import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.nio.file.*; -import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; -import java.sql.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Level; -import javax.sql.*; - -/** - * - * @author zhangjx - */ -public class JDBCPoolSource { - - private static final Map>>> maps = new HashMap<>(); - - private final AtomicLong usingCounter = new AtomicLong(); - - private final AtomicLong creatCounter = new AtomicLong(); - - private final AtomicLong cycleCounter = new AtomicLong(); - - private final AtomicLong saveCounter = new AtomicLong(); - - private final ConnectionPoolDataSource source; - - private final ArrayBlockingQueue queue; - - private final ConnectionEventListener listener; - - private final DataDefaultSource dataSource; - - private final String stype; // "" 或 "read" 或 "write" - - private final int max; - - private String url; - - private String user; - - private String password; - - public JDBCPoolSource(DataDefaultSource source, String stype, Properties prop) { - this.dataSource = source; - this.stype = stype; - this.source = createDataSource(prop); - this.url = prop.getProperty(JDBC_URL); - this.user = prop.getProperty(JDBC_USER); - this.password = prop.getProperty(JDBC_PWD); - this.max = Integer.decode(prop.getProperty(JDBC_CONNECTIONMAX, "" + Runtime.getRuntime().availableProcessors() * 16)); - this.queue = new ArrayBlockingQueue<>(this.max); - this.listener = new ConnectionEventListener() { - - @Override - public void connectionClosed(ConnectionEvent event) { - PooledConnection pc = (PooledConnection) event.getSource(); - if (queue.offer(pc)) saveCounter.incrementAndGet(); - } - - @Override - public void connectionErrorOccurred(ConnectionEvent event) { - usingCounter.decrementAndGet(); - if ("08S01".equals(event.getSQLException().getSQLState())) return; //MySQL特性, 长时间连接没使用会抛出com.mysql.jdbc.exceptions.jdbc4.CommunicationsException - dataSource.logger.log(Level.WARNING, "connectionErronOccurred [" + event.getSQLException().getSQLState() + "]", event.getSQLException()); - } - }; - try { - this.watch(); - } catch (Exception e) { - dataSource.logger.log(Level.WARNING, DataSource.class.getSimpleName() + " watch " + dataSource.conf + " error", e); - } - } - - public boolean isMysql() { - return source != null && source.getClass().getName().contains(".mysql."); - } - - private void watch() throws IOException { - if (dataSource.conf == null || dataSource.name == null) return; - final String file = dataSource.conf.getFile(); - final File f = new File(file); - if (!f.isFile() || !f.canRead()) return; - synchronized (maps) { - AbstractMap.SimpleEntry>> entry = maps.get(file); - if (entry != null) { - entry.getValue().add(new WeakReference<>(this)); - return; - } - final WatchService watcher = f.toPath().getFileSystem().newWatchService(); - final List> list = new CopyOnWriteArrayList<>(); - Thread watchThread = new Thread() { - - @Override - public void run() { - try { - while (!this.isInterrupted()) { - final WatchKey key = watcher.take(); - Thread.sleep(3000); //防止文件正在更新过程中去读取 - final Map m = loadProperties(new FileInputStream(file)); - key.pollEvents().stream().forEach((event) -> { - if (event.kind() != ENTRY_MODIFY) return; - if (!((Path) event.context()).toFile().getName().equals(f.getName())) return; - for (WeakReference ref : list) { - JDBCPoolSource pool = ref.get(); - if (pool == null) continue; - try { - Properties property = m.get(pool.dataSource.name); - if (property == null) property = m.get(pool.dataSource.name + "." + pool.stype); - if (property != null) pool.change(property); - } catch (Exception ex) { - dataSource.logger.log(Level.INFO, event.context() + " occur error", ex); - } - } - }); - key.reset(); - } - } catch (Exception e) { - dataSource.logger.log(Level.WARNING, "DataSource watch " + file + " occur error", e); - } - } - }; - f.getParentFile().toPath().register(watcher, ENTRY_MODIFY); - watchThread.setName("DataSource-Watch-" + maps.size() + "-Thread"); - watchThread.setDaemon(true); - watchThread.start(); - dataSource.logger.log(Level.FINER, watchThread.getName() + " start watching " + file); - //----------------------------------------------------------- - list.add(new WeakReference<>(this)); - maps.put(file, new AbstractMap.SimpleEntry<>(watcher, list)); - } - } - - public void change(Properties property) { - Method seturlm; - Class clazz = source.getClass(); - String newurl = property.getProperty(JDBC_URL); - String newuser = property.getProperty(JDBC_USER); - String newpassword = property.getProperty(JDBC_PWD); - if (this.url.equals(newurl) && this.user.equals(newuser) && this.password.equals(newpassword)) return; - try { - try { - seturlm = clazz.getMethod("setUrl", String.class); - } catch (Exception e) { - seturlm = clazz.getMethod("setURL", String.class); - } - seturlm.invoke(source, newurl); - clazz.getMethod("setUser", String.class).invoke(source, newuser); - clazz.getMethod("setPassword", String.class).invoke(source, newpassword); - this.url = newurl; - this.user = newuser; - this.password = newpassword; - dataSource.logger.log(Level.INFO, DataSource.class.getSimpleName() + "(" + dataSource.name + "." + stype + ") change (" + property + ")"); - } catch (Exception e) { - dataSource.logger.log(Level.SEVERE, DataSource.class.getSimpleName() + " dynamic change JDBC (url userName password) error", e); - } - } - - public Connection poll() { - return poll(0, null); - } - - private Connection poll(final int count, SQLException e) { - if (count >= 3) { - dataSource.logger.log(Level.WARNING, "create pooled connection error", e); - throw new RuntimeException(e); - } - PooledConnection result = queue.poll(); - if (result == null) { - if (usingCounter.get() >= max) { - try { - result = queue.poll(6, TimeUnit.SECONDS); - } catch (Exception t) { - dataSource.logger.log(Level.WARNING, "take pooled connection error", t); - } - } - if (result == null) { - try { - result = source.getPooledConnection(); - result.addConnectionEventListener(listener); - usingCounter.incrementAndGet(); - } catch (SQLException ex) { - return poll(count + 1, ex); - } - creatCounter.incrementAndGet(); - } - } else { - cycleCounter.incrementAndGet(); - } - Connection conn; - try { - conn = result.getConnection(); - if (!conn.isValid(1)) { - dataSource.logger.info("sql connection is not vaild"); - usingCounter.decrementAndGet(); - return poll(0, null); - } - } catch (SQLException ex) { - if (!"08S01".equals(ex.getSQLState())) {//MySQL特性, 长时间连接没使用会抛出com.mysql.jdbc.exceptions.jdbc4.CommunicationsException - dataSource.logger.log(Level.FINER, "result.getConnection from pooled connection abort [" + ex.getSQLState() + "]", ex); - } - return poll(0, null); - } - return conn; - } - - public long getCreatCount() { - return creatCounter.longValue(); - } - - public long getCycleCount() { - return cycleCounter.longValue(); - } - - public long getSaveCount() { - return saveCounter.longValue(); - } - - public void close() { - queue.stream().forEach(x -> { - try { - x.close(); - } catch (Exception e) { - } - }); - } -} diff --git a/src/com/wentch/redkale/source/Range.java b/src/com/wentch/redkale/source/Range.java deleted file mode 100644 index 8d3c6a92d..000000000 --- a/src/com/wentch/redkale/source/Range.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -/** - * - * @author zhangjx - * @param - */ -public interface Range extends java.io.Serializable { - - public E getMin(); - - public E getMax(); - - public static final class ByteRange implements Range { - - private Byte min = Byte.MIN_VALUE; - - private Byte max = Byte.MAX_VALUE; - - public ByteRange() { - } - - public ByteRange(Byte min, Byte max) { - if (min != null) this.min = min; - if (max != null) this.max = max; - } - - @Override - public Byte getMin() { - return min; - } - - @Override - public Byte getMax() { - return max; - } - - public void setMin(Byte min) { - if (min != null) this.min = min; - } - - public void setMax(Byte max) { - if (max != null) this.max = max; - } - - @Override - public String toString() { - return "{min:" + min + ", max:" + max + "}"; - } - } - - public static final class ShortRange implements Range { - - private Short min = Short.MIN_VALUE; - - private Short max = Short.MAX_VALUE; - - public ShortRange() { - } - - public ShortRange(Short min, Short max) { - if (min != null) this.min = min; - if (max != null) this.max = max; - } - - @Override - public Short getMin() { - return min; - } - - @Override - public Short getMax() { - return max; - } - - public void setMin(Short min) { - if (min != null) this.min = min; - } - - public void setMax(Short max) { - if (max != null) this.max = max; - } - - @Override - public String toString() { - return "{min:" + min + ", max:" + max + "}"; - } - } - - public static final class IntegerRange implements Range { - - private Integer min = Integer.MIN_VALUE; - - private Integer max = Integer.MAX_VALUE; - - public IntegerRange() { - } - - public IntegerRange(Integer min, Integer max) { - if (min != null) this.min = min; - if (max != null) this.max = max; - } - - @Override - public Integer getMin() { - return min; - } - - @Override - public Integer getMax() { - return max; - } - - public void setMin(Integer min) { - if (min != null) this.min = min; - } - - public void setMax(Integer max) { - if (max != null) this.max = max; - } - - @Override - public String toString() { - return "{min:" + min + ", max:" + max + "}"; - } - } - - public static final class LongRange implements Range { - - private Long min = Long.MIN_VALUE; - - private Long max = Long.MAX_VALUE; - - public LongRange() { - } - - public LongRange(Long min, Long max) { - if (min != null) this.min = min; - if (max != null) this.max = max; - } - - @Override - public Long getMin() { - return min; - } - - @Override - public Long getMax() { - return max; - } - - public void setMin(Long min) { - if (min != null) this.min = min; - } - - public void setMax(Long max) { - if (max != null) this.max = max; - } - - @Override - public String toString() { - return "{min:" + min + ", max:" + max + "}"; - } - } - - public static final class FloatRange implements Range { - - private Float min = Float.MIN_VALUE; - - private Float max = Float.MAX_VALUE; - - public FloatRange() { - } - - public FloatRange(Float min, Float max) { - if (min != null) this.min = min; - if (max != null) this.max = max; - } - - @Override - public Float getMin() { - return min; - } - - @Override - public Float getMax() { - return max; - } - - public void setMin(Float min) { - if (min != null) this.min = min; - } - - public void setMax(Float max) { - if (max != null) this.max = max; - } - - @Override - public String toString() { - return "{min:" + min + ", max:" + max + "}"; - } - } - - public static final class DoubleRange implements Range { - - private Double min = Double.MIN_VALUE; - - private Double max = Double.MAX_VALUE; - - public DoubleRange() { - } - - public DoubleRange(Double min, Double max) { - if (min != null) this.min = min; - if (max != null) this.max = max; - } - - @Override - public Double getMin() { - return min; - } - - @Override - public Double getMax() { - return max; - } - - public void setMin(Double min) { - if (min != null) this.min = min; - } - - public void setMax(Double max) { - if (max != null) this.max = max; - } - - @Override - public String toString() { - return "{min:" + min + ", max:" + max + "}"; - } - } - - public static final class StringRange implements Range { - - private String min = ""; - - private String max = ""; - - public StringRange() { - } - - public StringRange(String min, String max) { - this.min = min; - this.max = max; - } - - @Override - public String getMin() { - return min; - } - - @Override - public String getMax() { - return max; - } - - public void setMin(String min) { - this.min = min; - } - - public void setMax(String max) { - this.max = max; - } - - @Override - public String toString() { - return "{min:'" + min + "', max:'" + max + "'}"; - } - } -} diff --git a/src/com/wentch/redkale/source/ReckonType.java b/src/com/wentch/redkale/source/ReckonType.java deleted file mode 100644 index cd3f62fd9..000000000 --- a/src/com/wentch/redkale/source/ReckonType.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -/** - * - * @author zhangjx - */ -public enum ReckonType { - - AVG, COUNT, DISTINCTCOUNT, MAX, MIN, SUM; - - public String getReckonColumn(String col) { - if (this == COUNT) return this.name() + "(*)"; - if (this == DISTINCTCOUNT) return "COUNT(DISTINCT " + col + ")"; - return this.name() + "(" + col + ")"; - } -} diff --git a/src/com/wentch/redkale/source/VirtualEntity.java b/src/com/wentch/redkale/source/VirtualEntity.java deleted file mode 100644 index 5b5c67853..000000000 --- a/src/com/wentch/redkale/source/VirtualEntity.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * - * @author zhangjx - */ -@Documented -@Target(TYPE) -@Retention(RUNTIME) -public @interface VirtualEntity { - -} diff --git a/src/com/wentch/redkale/util/AnyValue.java b/src/com/wentch/redkale/util/AnyValue.java deleted file mode 100644 index cc5c024ba..000000000 --- a/src/com/wentch/redkale/util/AnyValue.java +++ /dev/null @@ -1,434 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.lang.reflect.Array; -import java.util.*; -import java.util.function.BiPredicate; - -/** - * 该类主要用于读取xml配置文件 - * - * @author zhangjx - */ -@SuppressWarnings("unchecked") -public interface AnyValue { - - /** - * 可读写的AnyValue默认实现类 - * - * @author zhangjx - */ - @SuppressWarnings("unchecked") - public static final class DefaultAnyValue implements AnyValue { - - public static final BiPredicate EQUALS = (String name1, String name2) -> name1.equals(name2); - - public static final BiPredicate EQUALSIGNORE = (String name1, String name2) -> name1.equalsIgnoreCase(name2); - - private final BiPredicate predicate; - - private Entry[] stringValues = new Entry[0]; - - private Entry[] entityValues = new Entry[0]; - - public static final DefaultAnyValue create() { - return new DefaultAnyValue(); - } - - public static final DefaultAnyValue create(String name, String value) { - DefaultAnyValue conf = new DefaultAnyValue(); - conf.addValue(name, value); - return conf; - } - - public static final DefaultAnyValue create(String name, AnyValue value) { - DefaultAnyValue conf = new DefaultAnyValue(); - conf.addValue(name, value); - return conf; - } - - public DefaultAnyValue() { - this(false); - } - - public DefaultAnyValue(boolean ignoreCase) { - this.predicate = ignoreCase ? EQUALSIGNORE : EQUALS; - } - - public DefaultAnyValue(BiPredicate predicate) { - this.predicate = predicate; - } - - public DefaultAnyValue duplicate() { - DefaultAnyValue rs = new DefaultAnyValue(this.predicate); - rs.stringValues = this.stringValues; - rs.entityValues = this.entityValues; - return rs; - } - - public DefaultAnyValue addAll(final AnyValue av) { - if (av == null) return this; - if (av instanceof DefaultAnyValue) { - final DefaultAnyValue adv = (DefaultAnyValue) av; - if (adv.stringValues != null) { - for (Entry en : adv.stringValues) { - this.addValue(en.name, en.value); - } - } - if (adv.entityValues != null) { - for (Entry en : adv.entityValues) { - this.addValue(en.name, en.value); - } - } - } else { - final Entry[] strings = av.getStringEntrys(); - if (strings != null) { - for (Entry en : strings) { - this.addValue(en.name, en.value); - } - } - final Entry[] anys = av.getAnyEntrys(); - if (anys != null) { - for (Entry en : anys) { - this.addValue(en.name, en.value); - } - } - } - return this; - } - - public DefaultAnyValue setAll(final AnyValue av) { - if (av == null) return this; - if (av instanceof DefaultAnyValue) { - final DefaultAnyValue adv = (DefaultAnyValue) av; - if (adv.stringValues != null) { - for (Entry en : adv.stringValues) { - this.setValue(en.name, en.value); - } - } - if (adv.entityValues != null) { - for (Entry en : adv.entityValues) { - this.setValue(en.name, en.value); - } - } - } else { - final Entry[] strings = av.getStringEntrys(); - if (strings != null) { - for (Entry en : strings) { - this.setValue(en.name, en.value); - } - } - final Entry[] anys = av.getAnyEntrys(); - if (anys != null) { - for (Entry en : anys) { - this.setValue(en.name, en.value); - } - } - } - return this; - } - - @Override - public Entry[] getStringEntrys() { - return stringValues; - } - - @Override - public Entry[] getAnyEntrys() { - return entityValues; - } - - @Override - public String[] getNames() { - Set set = new LinkedHashSet<>(); - for (Entry en : this.stringValues) { - set.add(en.name); - } - for (Entry en : this.entityValues) { - set.add(en.name); - } - return set.toArray(new String[set.size()]); - } - - @Override - public String[] getValues(String... names) { - return Entry.getValues(this.predicate, String.class, this.stringValues, names); - } - - @Override - public AnyValue[] getAnyValues(String... names) { - return Entry.getValues(this.predicate, AnyValue.class, this.entityValues, names); - } - - @Override - public String toString() { - return toString(0); - } - - public DefaultAnyValue clear() { - this.stringValues = new Entry[0]; - this.entityValues = new Entry[0]; - return this; - } - - public DefaultAnyValue setValue(String name, String value) { - if (name == null) return this; - if (getValue(name) == null) { - this.addValue(name, value); - } else { - for (Entry en : this.stringValues) { - if (predicate.test(en.name, name)) { - en.value = value; - return this; - } - } - } - return this; - } - - public DefaultAnyValue setValue(String name, AnyValue value) { - if (name == null) return this; - if (getValue(name) == null) { - this.addValue(name, value); - } else { - for (Entry en : this.entityValues) { - if (predicate.test(en.name, name)) { - en.value = value; - return this; - } - } - } - return this; - } - - public DefaultAnyValue addValue(String name, String value) { - if (name == null) return this; - int len = this.stringValues.length; - Entry[] news = new Entry[len + 1]; - System.arraycopy(this.stringValues, 0, news, 0, len); - news[len] = new Entry(name, value); - this.stringValues = news; - return this; - } - - public DefaultAnyValue addValue(String name, AnyValue value) { - if (name == null || value == null) return this; - int len = this.entityValues.length; - Entry[] news = new Entry[len + 1]; - System.arraycopy(this.entityValues, 0, news, 0, len); - news[len] = new Entry(name, value); - this.entityValues = news; - return this; - } - - @Override - public AnyValue getAnyValue(String name) { - for (Entry en : this.entityValues) { - if (predicate.test(en.name, name)) { - return en.value; - } - } - return null; - } - - @Override - public String getValue(String name) { - for (Entry en : this.stringValues) { - if (predicate.test(en.name, name)) { - return en.value; - } - } - return null; - } - - @Override - public String[] getValues(String name) { - return Entry.getValues(this.predicate, String.class, this.stringValues, name); - } - - @Override - public AnyValue[] getAnyValues(String name) { - return Entry.getValues(this.predicate, AnyValue.class, this.entityValues, name); - } - - } - - public final class Entry { - - public final String name; - - T value; - - public Entry(String name0, T value0) { - this.name = name0; - this.value = value0; - } - - public T getValue() { - return value; - } - - static T[] getValues(BiPredicate comparison, Class clazz, Entry[] entitys, String name) { - int len = 0; - for (Entry en : entitys) { - if (comparison.test(en.name, name)) { - ++len; - } - } - if (len == 0) return (T[]) Array.newInstance(clazz, len); - T[] rs = (T[]) Array.newInstance(clazz, len); - int i = 0; - for (Entry en : entitys) { - if (comparison.test(en.name, name)) { - rs[i++] = en.value; - } - } - return rs; - } - - static T[] getValues(BiPredicate comparison, Class clazz, Entry[] entitys, String... names) { - int len = 0; - for (Entry en : entitys) { - for (String name : names) { - if (comparison.test(en.name, name)) { - ++len; - break; - } - } - } - if (len == 0) return (T[]) Array.newInstance(clazz, len); - T[] rs = (T[]) Array.newInstance(clazz, len); - int i = 0; - for (Entry en : entitys) { - for (String name : names) { - if (comparison.test(en.name, name)) { - rs[i++] = en.value; - break; - } - } - } - return rs; - } - } - - public static AnyValue create() { - return new DefaultAnyValue(); - } - - default String toString(int len) { - if (len < 0) len = 0; - char[] chars = new char[len]; - Arrays.fill(chars, ' '); - final String space = new String(chars); - StringBuilder sb = new StringBuilder(); - sb.append("{\r\n"); - for (Entry en : getStringEntrys()) { - sb.append(space).append(" '").append(en.name).append("': '").append(en.value).append("',\r\n"); - } - for (Entry en : getAnyEntrys()) { - sb.append(space).append(" '").append(en.name).append("': '").append(en.value.toString(len + 4)).append("',\r\n"); - } - sb.append(space).append('}'); - return sb.toString(); - } - - public Entry[] getStringEntrys(); - - public Entry[] getAnyEntrys(); - - public String[] getNames(); - - public String[] getValues(String name); - - public String[] getValues(String... names); - - public AnyValue[] getAnyValues(String name); - - public AnyValue[] getAnyValues(String... names); - - public AnyValue getAnyValue(String name); - - public String getValue(String name); - - default boolean getBoolValue(String name) { - return Boolean.parseBoolean(getValue(name)); - } - - default boolean getBoolValue(String name, boolean defaultValue) { - String value = getValue(name); - return value == null ? defaultValue : Boolean.parseBoolean(value); - } - - default byte getByteValue(String name) { - return Byte.parseByte(getValue(name)); - } - - default byte getByteValue(String name, byte defaultValue) { - String value = getValue(name); - return value == null ? defaultValue : Byte.decode(value); - } - - default char getCharValue(String name) { - return getValue(name).charAt(0); - } - - default char getCharValue(String name, char defaultValue) { - String value = getValue(name); - return value == null || value.length() == 0 ? defaultValue : value.charAt(0); - } - - default short getShortValue(String name) { - return Short.decode(getValue(name)); - } - - default short getShortValue(String name, short defaultValue) { - String value = getValue(name); - return value == null ? defaultValue : Short.decode(value); - } - - default int getIntValue(String name) { - return Integer.decode(getValue(name)); - } - - default int getIntValue(String name, int defaultValue) { - String value = getValue(name); - return value == null ? defaultValue : Integer.decode(value); - } - - default long getLongValue(String name) { - return Long.decode(getValue(name)); - } - - default long getLongValue(String name, long defaultValue) { - String value = getValue(name); - return value == null ? defaultValue : Long.decode(value); - } - - default float getFloatValue(String name) { - return Float.parseFloat(getValue(name)); - } - - default float getFloatValue(String name, float defaultValue) { - String value = getValue(name); - return value == null ? defaultValue : Float.parseFloat(value); - } - - default double getDoubleValue(String name) { - return Double.parseDouble(getValue(name)); - } - - default double getDoubleValue(String name, double defaultValue) { - String value = getValue(name); - return value == null ? defaultValue : Double.parseDouble(value); - } - - default String getValue(String name, String defaultValue) { - String value = getValue(name); - return value == null ? defaultValue : value; - } - -} diff --git a/src/com/wentch/redkale/util/Attribute.java b/src/com/wentch/redkale/util/Attribute.java deleted file mode 100644 index d10c8b0af..000000000 --- a/src/com/wentch/redkale/util/Attribute.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.lang.reflect.*; -import static jdk.internal.org.objectweb.asm.Opcodes.*; -import jdk.internal.org.objectweb.asm.Type; - -/** - * 该类功能是动态映射一个Data类中成员对应的getter、setter方法; 代替低效的反射实现方式。 - * 映射Field时,field要么是public非final,要么存在对应的getter、setter方法。 - * - * @author zhangjx - * @param - * @param - */ -public interface Attribute { - - public Class type(); - - public Class declaringClass(); - - public String field(); - - public F get(T obj); - - public void set(T obj, F value); - - /** - * 根据一个Field生成 Attribute 对象。 - * - * @param - * @param - * @param field - * @return - */ - public static Attribute create(final Field field) { - return create((Class) field.getDeclaringClass(), field.getName(), field, null, null); - } - - /** - * 根据一个Field和field的别名生成 Attribute 对象。 - * - * @param - * @param - * @param fieldname 别名 - * @param field - * @return - */ - public static Attribute create(String fieldname, final Field field) { - return create((Class) field.getDeclaringClass(), fieldname, field, null, null); - } - - /** - * 根据一个Class和field名生成 Attribute 对象。 - * - * @param - * @param - * @param clazz - * @param fieldname 字段名, 如果该字段不存在则抛异常 - * @return - */ - public static Attribute create(Class clazz, final String fieldname) { - try { - return create(clazz, fieldname, clazz.getDeclaredField(fieldname), null, null); - } catch (NoSuchFieldException | SecurityException ex) { - throw new RuntimeException(ex); - } - } - - public static Attribute create(Class clazz, final java.lang.reflect.Field field) { - return create(clazz, field.getName(), field); - } - - public static Attribute create(Class clazz, final String fieldname, final java.lang.reflect.Field field) { - return create(clazz, fieldname, field, null, null); - } - - public static Attribute create(final Method getter, final Method setter) { - return create((Class) (getter == null ? setter.getDeclaringClass() : getter.getDeclaringClass()), null, null, getter, setter); - } - - public static Attribute create(Class clazz, final Method getter, final Method setter) { - return create(clazz, null, null, getter, setter); - } - - public static Attribute create(Class clazz, final String fieldalias, final Method getter, final Method setter) { - return create(clazz, fieldalias, null, getter, setter); - } - - @SuppressWarnings("unchecked") - public static Attribute create(final Class clazz, String fieldalias0, final Field field0, Method getter0, Method setter0) { - if (fieldalias0 != null && fieldalias0.isEmpty()) fieldalias0 = null; - int mod = field0 == null ? Modifier.STATIC : field0.getModifiers(); - if (field0 != null && !Modifier.isStatic(mod) && !Modifier.isPublic(mod)) { - Class t = field0.getType(); - char[] fs = field0.getName().toCharArray(); - fs[0] = Character.toUpperCase(fs[0]); - String mn = new String(fs); - if (getter0 == null) { - String prefix = t == boolean.class || t == Boolean.class ? "is" : "get"; - try { - getter0 = clazz.getMethod(prefix + mn); - } catch (Exception ex) { - } - } - if (setter0 == null) { - try { - setter0 = clazz.getMethod("set" + mn, field0.getType()); - } catch (Exception ex) { - } - } - } - final Field field = field0 == null ? null : (!Modifier.isPublic(mod) || Modifier.isStatic(mod) ? null : field0); - final java.lang.reflect.Method getter = getter0; - final java.lang.reflect.Method setter = setter0; - if (fieldalias0 == null) { - if (field0 != null) { - fieldalias0 = field0.getName(); - } else { - String s; - if (getter0 != null) { - s = getter0.getName().substring(getter0.getName().startsWith("is") ? 2 : 3); - } else { - s = setter0.getName().substring(3); - } - char[] d = s.toCharArray(); - if (d.length < 2 || Character.isLowerCase(d[1])) { - d[0] = Character.toLowerCase(d[0]); - } - fieldalias0 = new String(d); - } - } - if (getter == null && setter == null && field == null) { - throw new RuntimeException("[" + clazz + "]have no public field or setter or getter"); - } - final String fieldname = fieldalias0; - Class column; - if (field != null) { // public field - column = field.getType(); - } else if (getter != null) { - column = getter.getReturnType(); - } else { // setter != null - column = setter.getParameterTypes()[0]; - } - final Class pcolumn = column; - if (column.isPrimitive()) column = Array.get(Array.newInstance(column, 1), 0).getClass(); - final String supDynName = Attribute.class.getName().replace('.', '/'); - final String interName = clazz.getName().replace('.', '/'); - final String columnName = column.getName().replace('.', '/'); - final String interDesc = Type.getDescriptor(clazz); - final String columnDesc = Type.getDescriptor(column); - - ClassLoader loader = Attribute.class.getClassLoader(); - String newDynName = supDynName + "_Dyn_" + clazz.getSimpleName() + "_" - + fieldname.substring(fieldname.indexOf('.') + 1) + "_" + pcolumn.getSimpleName().replace("[]", "Array"); - if (String.class.getClassLoader() != clazz.getClassLoader()) { - loader = clazz.getClassLoader(); - newDynName = interName + "_Dyn" + Attribute.class.getSimpleName() + "_" - + fieldname.substring(fieldname.indexOf('.') + 1) + "_" + pcolumn.getSimpleName().replace("[]", "Array"); - } - try { - return (Attribute) Class.forName(newDynName.replace('/', '.')).newInstance(); - } catch (Exception ex) { - } - //--------------------------------------------------- - final jdk.internal.org.objectweb.asm.ClassWriter cw = new jdk.internal.org.objectweb.asm.ClassWriter(0); - jdk.internal.org.objectweb.asm.MethodVisitor mv; - - cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;L" + supDynName + "<" + interDesc + columnDesc + ">;", "java/lang/Object", new String[]{supDynName}); - - { //构造方法 - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - - { //field 方法 - mv = cw.visitMethod(ACC_PUBLIC, "field", "()Ljava/lang/String;", null, null); - mv.visitLdcInsn(fieldname); - mv.visitInsn(ARETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - { //type 方法 - mv = cw.visitMethod(ACC_PUBLIC, "type", "()Ljava/lang/Class;", null, null); - if (pcolumn == boolean.class) { - mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;"); - } else if (pcolumn == byte.class) { - mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;"); - } else if (pcolumn == char.class) { - mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;"); - } else if (pcolumn == short.class) { - mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;"); - } else if (pcolumn == int.class) { - mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;"); - } else if (pcolumn == float.class) { - mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;"); - } else if (pcolumn == long.class) { - mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;"); - } else if (pcolumn == double.class) { - mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;"); - } else { - mv.visitLdcInsn(Type.getType(pcolumn)); - } - mv.visitInsn(ARETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - { //declaringClass 方法 - mv = cw.visitMethod(ACC_PUBLIC, "declaringClass", "()Ljava/lang/Class;", null, null); - mv.visitLdcInsn(Type.getType(clazz)); - mv.visitInsn(ARETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - { //get 方法 - mv = cw.visitMethod(ACC_PUBLIC, "get", "(" + interDesc + ")" + columnDesc, null, null); - int m = 1; - if (getter == null) { - if (field == null) { - mv.visitInsn(ACONST_NULL); - } else { //public field - mv.visitVarInsn(ALOAD, 1); - mv.visitFieldInsn(GETFIELD, interName, field.getName(), Type.getDescriptor(pcolumn)); - if (pcolumn != column) { - mv.visitMethodInsn(INVOKESTATIC, columnName, "valueOf", "(" + Type.getDescriptor(pcolumn) + ")" + columnDesc, false); - m = 2; - } - } - } else { - mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn(INVOKEVIRTUAL, interName, getter.getName(), Type.getMethodDescriptor(getter), false); - if (pcolumn != column) { - mv.visitMethodInsn(INVOKESTATIC, columnName, "valueOf", "(" + Type.getDescriptor(pcolumn) + ")" + columnDesc, false); - m = 2; - } - } - mv.visitInsn(ARETURN); - mv.visitMaxs(m, 2); - mv.visitEnd(); - } - { //set 方法 - mv = cw.visitMethod(ACC_PUBLIC, "set", "(" + interDesc + columnDesc + ")V", null, null); - int m = 2; - if (setter == null) { - if (field == null || Modifier.isFinal(field.getModifiers())) { - m = 0; - } else { //public field - mv.visitVarInsn(ALOAD, 1); - mv.visitVarInsn(ALOAD, 2); - if (pcolumn != column) { - try { - java.lang.reflect.Method pm = column.getMethod(pcolumn.getSimpleName() + "Value"); - mv.visitMethodInsn(INVOKEVIRTUAL, columnName, pm.getName(), Type.getMethodDescriptor(pm), false); - m = 3; - } catch (Exception ex) { - throw new RuntimeException(ex); //不可能会发生 - } - } - mv.visitFieldInsn(PUTFIELD, interName, field.getName(), Type.getDescriptor(pcolumn)); - } - } else { - mv.visitVarInsn(ALOAD, 1); - mv.visitVarInsn(ALOAD, 2); - if (pcolumn != column) { - try { - java.lang.reflect.Method pm = column.getMethod(pcolumn.getSimpleName() + "Value"); - mv.visitMethodInsn(INVOKEVIRTUAL, columnName, pm.getName(), Type.getMethodDescriptor(pm), false); - m = 3; - } catch (Exception ex) { - throw new RuntimeException(ex); //不可能会发生 - } - } - mv.visitMethodInsn(INVOKEVIRTUAL, interName, setter.getName(), Type.getMethodDescriptor(setter), false); - } - mv.visitInsn(RETURN); - mv.visitMaxs(m, 3); - mv.visitEnd(); - } - { //虚拟get - mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", null, null); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 1); - mv.visitTypeInsn(CHECKCAST, interName); - mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "get", "(" + interDesc + ")" + columnDesc, false); - mv.visitInsn(ARETURN); - mv.visitMaxs(2, 2); - mv.visitEnd(); - } - {//虚拟set - mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 1); - mv.visitTypeInsn(CHECKCAST, interName); - mv.visitVarInsn(ALOAD, 2); - mv.visitTypeInsn(CHECKCAST, columnName); - mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "set", "(" + interDesc + columnDesc + ")V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(3, 3); - mv.visitEnd(); - } - cw.visitEnd(); - - byte[] bytes = cw.toByteArray(); - Class creatorClazz = (Class) new ClassLoader(loader) { - public final Class loadClass(String name, byte[] b) { - return defineClass(name, b, 0, b.length); - } - }.loadClass(newDynName.replace('/', '.'), bytes); - try { - return creatorClazz.newInstance(); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } -} diff --git a/src/com/wentch/redkale/util/AutoLoad.java b/src/com/wentch/redkale/util/AutoLoad.java deleted file mode 100644 index 68686adbe..000000000 --- a/src/com/wentch/redkale/util/AutoLoad.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * 自动全量缓存 - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({TYPE}) -@Retention(RUNTIME) -public @interface AutoLoad { - - boolean value() default true; -} diff --git a/src/com/wentch/redkale/util/ByteArray.java b/src/com/wentch/redkale/util/ByteArray.java deleted file mode 100644 index 4dc85bbbf..000000000 --- a/src/com/wentch/redkale/util/ByteArray.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.nio.*; -import java.nio.charset.*; - -/** - * - * @author zhangjx - */ -public final class ByteArray { - - private byte[] content; - - private int count; - - public ByteArray() { - this(1024); - } - - public ByteArray(int size) { - content = new byte[Math.max(128, size)]; - } - - public void clear() { - this.count = 0; - } - - public int find(byte value) { - return find(0, value); - } - - public boolean equal(final byte[] bytes) { - if (bytes == null || count != bytes.length) return false; - for (int i = 0; i < count; i++) { - if (content[i] != bytes[i]) return false; - } - return true; - } - - public boolean isEmpty() { - return count == 0; - } - - public int count() { - return count; - } - - public void write(byte[] buf) { - System.arraycopy(this.content, 0, buf, 0, count); - } - - public byte[] directBytes() { - return content; - } - - public int find(int offset, char value) { - return find(offset, (byte) value); - } - - public int find(int offset, byte value) { - return find(offset, -1, value); - } - - public int find(int offset, int limit, char value) { - return find(offset, limit, (byte) value); - } - - public int find(int offset, int limit, byte value) { - byte[] bytes = this.content; - int end = limit > 0 ? limit : count; - for (int i = offset; i < end; i++) { - if (bytes[i] == value) return i; - } - return -1; - } - - public void removeLastByte() { - if (count > 0) count--; - } - - public void addInt(int value) { - add((byte) (value >> 24 & 0xFF), (byte) (value >> 16 & 0xFF), (byte) (value >> 8 & 0xFF), (byte) (value & 0xFF)); - } - - public void add(byte value) { - if (count >= content.length - 1) { - byte[] ns = new byte[content.length + 8]; - System.arraycopy(content, 0, ns, 0, count); - this.content = ns; - } - content[count++] = value; - } - - public void add(byte... values) { - if (count >= content.length - values.length) { - byte[] ns = new byte[content.length + values.length]; - System.arraycopy(content, 0, ns, 0, count); - this.content = ns; - } - System.arraycopy(content, count, values, 0, values.length); - count += values.length; - } - - public void add(ByteBuffer buffer, int len) { - if (len < 1) return; - if (count >= content.length - len) { - byte[] ns = new byte[content.length + len]; - System.arraycopy(content, 0, ns, 0, count); - this.content = ns; - } - buffer.get(content, count, len); - count += len; - } - - @Override - public String toString() { - return new String(content, 0, count); - } - - public String toString(final Charset charset) { - return toString(0, count, charset); - } - - public String toString(final int offset, int len, final Charset charset) { - if (charset == null) return new String(Utility.decodeUTF8(content, offset, len)); - return new String(content, offset, len, charset); - } - - public String toDecodeString(final int offset, int len, final Charset charset) { - int index = offset; - for (int i = offset; i < (offset + len); i++) { - if (content[i] == '+') { - content[index] = ' '; - } else if (content[i] == '%') { - content[index] = (byte) ((hexBit(content[++i]) * 16 + hexBit(content[++i]))); - } else { - content[index] = content[i]; - } - index++; - } - for (int i = index + 1; i < (offset + len); i++) { - content[i] = ' '; - } - len = index - offset; - if (charset == null) return new String(Utility.decodeUTF8(content, offset, len)); - return new String(content, offset, len, charset); - } - - private static int hexBit(byte b) { - if ('0' <= b && '9' >= b) return b - '0'; - if ('a' <= b && 'z' >= b) return b - 'a' + 10; - if ('A' <= b && 'Z' >= b) return b - 'A' + 10; - return b; - } - -} diff --git a/src/com/wentch/redkale/util/Creator.java b/src/com/wentch/redkale/util/Creator.java deleted file mode 100644 index 27024104c..000000000 --- a/src/com/wentch/redkale/util/Creator.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.beans.ConstructorProperties; -import java.lang.reflect.*; -import java.util.*; -import jdk.internal.org.objectweb.asm.*; -import static jdk.internal.org.objectweb.asm.Opcodes.*; -import jdk.internal.org.objectweb.asm.Type; - -/** - * 实现一个类的构造方法。 代替低效的反射实现方式。 - * - * @author zhangjx - * @param - */ -public interface Creator { -// -// static class PooledCreator implements Creator { -// -// private final T defValue; -// -// private final Reproduce reproduce; -// -// private final ReferenceQueue refQueue = new ReferenceQueue(); -// -// private final Queue queue; -// -// private final Creator creator; -// -// public PooledCreator(int max, Class clazz, Creator creator) { -// this.creator = creator; -// this.defValue = creator.create(); -// this.reproduce = Reproduce.create(clazz, clazz); -// this.queue = new ArrayBlockingQueue<>(Math.max(Runtime.getRuntime().availableProcessors() * 2, max)); -// new Thread() { -// { -// setDaemon(true); -// setName(PooledCreator.class.getSimpleName() + " " + clazz.getSimpleName() + " Reference Handler"); -// } -// -// @Override -// public void run() { -// try { -// for (;;) { -// T r = refQueue.remove().get(); -// if (r == null) continue; -// reproduce.copy(r, defValue); -// queue.offer(r); -// } -// } catch (Exception e) { -// //do nothind -// } -// } -// }.start(); -// } -// -// @Override -// public T create(Object... params) { -// T rs = queue.poll(); -// if (rs == null) { -// rs = creator.create(params); -// } -// return new WeakReference<>(rs, refQueue).get(); -// } -// -// } -// -// @SuppressWarnings("unchecked") -// public static Creator create(int max, Class clazz) { -// return new PooledCreator<>(max, clazz, create(clazz)); -// } -// -// @SuppressWarnings("unchecked") -// public static Creator create(int max, Class clazz, Creator creator) { -// return new PooledCreator<>(max, clazz, creator); -// } - - public T create(Object... params); - - @SuppressWarnings("unchecked") - public static Creator create(Class clazz) { - if (clazz.isAssignableFrom(ArrayList.class)) { - clazz = (Class) ArrayList.class; - } else if (clazz.isAssignableFrom(HashMap.class)) { - clazz = (Class) HashMap.class; - } else if (clazz.isAssignableFrom(HashSet.class)) { - clazz = (Class) HashSet.class; - } - if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) { - throw new RuntimeException("[" + clazz + "] is a interface or abstract class, cannot create it's Creator."); - } - final String supDynName = Creator.class.getName().replace('.', '/'); - final String interName = clazz.getName().replace('.', '/'); - final String interDesc = Type.getDescriptor(clazz); - ClassLoader loader = Creator.class.getClassLoader(); - String newDynName = supDynName + "_" + clazz.getSimpleName() + "_" + (System.currentTimeMillis() % 10000); - if (String.class.getClassLoader() != clazz.getClassLoader()) { - loader = clazz.getClassLoader(); - newDynName = interName + "_Dyn" + Creator.class.getSimpleName(); - } - try { - return (Creator) Class.forName(newDynName.replace('/', '.')).newInstance(); - } catch (Exception ex) { - } - Constructor constructor = null; - for (Constructor c : clazz.getConstructors()) { - if (c.getParameterCount() == 0) { - constructor = c; - break; - } - } - if (constructor == null) { - for (Constructor c : clazz.getConstructors()) { - if (c.getAnnotation(ConstructorProperties.class) != null) { - constructor = c; - break; - } - } - } - if (constructor == null) throw new RuntimeException("[" + clazz + "] have no public or java.beans.ConstructorProperties-Annotation constructor."); - //------------------------------------------------------------- - ClassWriter cw = new ClassWriter(0); - FieldVisitor fv; - MethodVisitor mv; - AnnotationVisitor av0; - cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;L" + supDynName + "<" + interDesc + ">;", "java/lang/Object", new String[]{supDynName}); - - {//构造方法 - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - ConstructorProperties cps = constructor.getAnnotation(ConstructorProperties.class); - if (cps != null) { - av0 = mv.visitAnnotation(Type.getDescriptor(ConstructorProperties.class), true); - AnnotationVisitor av1 = av0.visitArray("value"); - for (String n : cps.value()) { - av1.visit(null, n); - } - av1.visitEnd(); - av0.visitEnd(); - } - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - {//create 方法 - mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)L" + interName + ";", null, null); - mv.visitTypeInsn(NEW, interName); - mv.visitInsn(DUP); - //--------------------------------------- - { - Parameter[] params = constructor.getParameters(); - final int[] iconsts = {ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5}; - for (int i = 0; i < params.length; i++) { - mv.visitVarInsn(ALOAD, 1); - if (i < 6) { - mv.visitInsn(iconsts[i]); - } else { - mv.visitIntInsn(BIPUSH, i); - } - mv.visitInsn(AALOAD); - Class ct = params[i].getType(); - mv.visitTypeInsn(CHECKCAST, Type.getInternalName(ct)); - if (ct.isPrimitive()) { - Class fct = Array.get(Array.newInstance(ct, 1), 0).getClass(); - try { - Method pm = ct.getMethod(ct.getSimpleName() + "Value"); - mv.visitMethodInsn(INVOKEVIRTUAL, fct.getName().replace('.', '/'), pm.getName(), Type.getMethodDescriptor(pm), false); - } catch (Exception ex) { - throw new RuntimeException(ex); //不可能会发生 - } - } - } - } - //--------------------------------------- - mv.visitMethodInsn(INVOKESPECIAL, interName, "", Type.getConstructorDescriptor(constructor), false); - mv.visitInsn(ARETURN); - mv.visitMaxs((constructor.getParameterCount() > 0 ? (constructor.getParameterCount() + 3) : 2), 2); - mv.visitEnd(); - } - { //虚拟 create 方法 - mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_VARARGS + ACC_SYNTHETIC, "create", "([Ljava/lang/Object;)Ljava/lang/Object;", null, null); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "create", "([Ljava/lang/Object;)" + interDesc, false); - mv.visitInsn(ARETURN); - mv.visitMaxs(2, 2); - mv.visitEnd(); - } - cw.visitEnd(); - byte[] bytes = cw.toByteArray(); - Class creatorClazz = new ClassLoader(loader) { - public final Class loadClass(String name, byte[] b) { - return defineClass(name, b, 0, b.length); - } - }.loadClass(newDynName.replace('/', '.'), bytes); - try { - return (Creator) creatorClazz.newInstance(); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } -} diff --git a/src/com/wentch/redkale/util/DLong.java b/src/com/wentch/redkale/util/DLong.java deleted file mode 100644 index c67966a7b..000000000 --- a/src/com/wentch/redkale/util/DLong.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -/** - * - * @author zhangjx - */ -public final class DLong extends Number implements Comparable { - - private final long first; - - private final long second; - - public DLong(long one, long two) { - this.first = one; - this.second = two; - } - - public long getFirst() { - return first; - } - - public long getSecond() { - return second; - } - - public boolean equals(long one, long two) { - return this.first == one && this.second == two; - } - - @Override - public boolean equals(Object obj) { - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - final DLong other = (DLong) obj; - return (this.first == other.first && this.second == other.second); - } - - @Override - public int hashCode() { - int hash = 7; - hash = 89 * hash + (int) (this.first ^ (this.first >>> 32)); - hash = 89 * hash + (int) (this.second ^ (this.second >>> 32)); - return hash; - } - - @Override - public String toString() { - return this.first + "_" + this.second; - } - - @Override - public int intValue() { - return (int) longValue(); - } - - @Override - public long longValue() { - return first ^ second; - } - - @Override - public float floatValue() { - return (float) longValue(); - } - - @Override - public double doubleValue() { - return (double) longValue(); - } - - @Override - public int compareTo(DLong o) { - return (int) (first == o.first ? (second - o.second) : (first - o.first)); - } - -} diff --git a/src/com/wentch/redkale/util/DebugMethodVisitor.java b/src/com/wentch/redkale/util/DebugMethodVisitor.java deleted file mode 100644 index 4fec6c4d3..000000000 --- a/src/com/wentch/redkale/util/DebugMethodVisitor.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.util.*; -import jdk.internal.org.objectweb.asm.*; - -/** - * - * @author zhangjx - */ -public class DebugMethodVisitor { - - private final MethodVisitor visitor; - - private boolean debug = false; - - public DebugMethodVisitor setDebug(boolean d) { - debug = d; - return this; - } - - private final Map labels = new LinkedHashMap<>(); - - private static final String[] opcodes = new String[200]; //0 -18 - - static { - try { - for (java.lang.reflect.Field field : Opcodes.class.getFields()) { - String name = field.getName(); - if (name.startsWith("ASM")) continue; - if (name.startsWith("V1_")) continue; - if (name.startsWith("ACC_")) continue; - if (name.startsWith("T_")) continue; - if (name.startsWith("H_")) continue; - if (name.startsWith("F_")) continue; - if (field.getType() != int.class) continue; - opcodes[(int) field.get(null)] = name; - } - } catch (Exception ex) { - throw new RuntimeException(ex); //不可能会发生 - } - } - - public DebugMethodVisitor(MethodVisitor visitor) { - //super(Opcodes.ASM5, visitor); - this.visitor = visitor; - } - - public AnnotationVisitor visitParameterAnnotation(int i, String string, boolean bln) { - AnnotationVisitor av = visitor.visitParameterAnnotation(i, string, bln); - if (debug) System.out.println("mv.visitParameterAnnotation(" + i + ", \"" + string + "\", " + bln + ");"); - return av; - } - - public AnnotationVisitor visitAnnotation(String desc, boolean flag) { - AnnotationVisitor av = visitor.visitAnnotation(desc, flag); - if (debug) System.out.println("mv.visitAnnotation(\"" + desc + "\", " + flag + ");"); - return av; - } - - public void visitParameter(String name, int access) { - visitor.visitParameter(name, access); - if (debug) System.out.println("mv.visitParameter(" + name + ", " + access + ");"); - } - - public void visitVarInsn(int opcode, int var) { - visitor.visitVarInsn(opcode, var); - if (debug) System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");"); - } - - public void visitJumpInsn(int opcode, Label var) { //调用次方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建 - visitor.visitJumpInsn(opcode, var); - if (debug) { - Integer index = labels.get(var); - if (index == null) { - index = labels.size(); - labels.put(var, index); - System.out.println("Label l" + index + " = new Label();"); - } - System.out.println("mv.visitJumpInsn(" + opcodes[opcode] + ", l" + index + ");"); - } - } - - public void visitCode() { - visitor.visitCode(); - if (debug) System.out.println("mv.visitCode();"); - } - - public void visitLabel(Label var) { - visitor.visitLabel(var); - if (debug) { - Integer index = labels.get(var); - if (index == null) { - index = labels.size(); - labels.put(var, index); - System.out.println("Label l" + index + " = new Label();"); - } - System.out.println("mv.visitLabel(l" + index + ");"); - } - } - - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - visitor.visitMethodInsn(opcode, owner, name, desc, itf); - if (debug) System.out.println("mv.visitMethodInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\", " + itf + ");"); - } - - public void visitFieldInsn(int opcode, String owner, String name, String desc) { - visitor.visitFieldInsn(opcode, owner, name, desc); - if (debug) System.out.println("mv.visitFieldInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\");"); - } - - public void visitTypeInsn(int opcode, String type) { - visitor.visitTypeInsn(opcode, type); - if (debug) System.out.println("mv.visitTypeInsn(" + opcodes[opcode] + ", \"" + type + "\");"); - } - - public void visitInsn(int opcode) { - visitor.visitInsn(opcode); - if (debug) System.out.println("mv.visitInsn(" + opcodes[opcode] + ");"); - } - - public void visitIntInsn(int opcode, int value) { - visitor.visitIntInsn(opcode, value); - if (debug) System.out.println("mv.visitIntInsn(" + opcodes[opcode] + ", " + value + ");"); - } - - public void visitIincInsn(int opcode, int value) { - visitor.visitIincInsn(opcode, value); - if (debug) System.out.println("mv.visitIincInsn(" + opcode + ", " + value + ");"); - } - - public void visitLdcInsn(Object o) { - visitor.visitLdcInsn(o); - if (debug) System.out.println("mv.visitLdcInsn(" + o + ");"); - } - - public void visitMaxs(int maxStack, int maxLocals) { - visitor.visitMaxs(maxStack, maxLocals); - if (debug) System.out.println("mv.visitMaxs(" + maxStack + ", " + maxLocals + ");"); - } - - public void visitEnd() { - visitor.visitEnd(); - if (debug) System.out.println("mv.visitEnd();\r\n\r\n\r\n"); - } -} diff --git a/src/com/wentch/redkale/util/Ignore.java b/src/com/wentch/redkale/util/Ignore.java deleted file mode 100644 index 3c83e1e67..000000000 --- a/src/com/wentch/redkale/util/Ignore.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({TYPE, FIELD, METHOD}) -@Retention(RUNTIME) -public @interface Ignore { - -} diff --git a/src/com/wentch/redkale/util/LogLevel.java b/src/com/wentch/redkale/util/LogLevel.java deleted file mode 100644 index f5e675530..000000000 --- a/src/com/wentch/redkale/util/LogLevel.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * 被标记的日志级别以上的才会被记录 - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({TYPE}) -@Retention(RUNTIME) -public @interface LogLevel { - - String value(); -} diff --git a/src/com/wentch/redkale/util/Nameable.java b/src/com/wentch/redkale/util/Nameable.java deleted file mode 100644 index af0128430..000000000 --- a/src/com/wentch/redkale/util/Nameable.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -/** - * - * @author zhangjx - */ -public interface Nameable { - - String name(); -} diff --git a/src/com/wentch/redkale/util/ObjectNode.java b/src/com/wentch/redkale/util/ObjectNode.java deleted file mode 100644 index fcf69288a..000000000 --- a/src/com/wentch/redkale/util/ObjectNode.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.util.*; - -/** - * - * @author zhangjx - */ -public class ObjectNode extends HashMap { - - public static ObjectNode create(String key, Object value) { - ObjectNode node = new ObjectNode(); - node.put(key, value); - return node; - } - - public ObjectNode appand(String key, Object value) { - this.put(key, value); - return this; - } -} diff --git a/src/com/wentch/redkale/util/ObjectPool.java b/src/com/wentch/redkale/util/ObjectPool.java deleted file mode 100644 index bff6c0381..000000000 --- a/src/com/wentch/redkale/util/ObjectPool.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import java.util.function.*; -import java.util.logging.*; - -/** - * - * @author zhangjx - * @param - */ -public final class ObjectPool implements Supplier { - - private static final Logger logger = Logger.getLogger(ObjectPool.class.getSimpleName()); - - private final boolean debug; - - private final Queue queue; - - private Creator creator; - - private final Consumer prepare; - - private final Predicate recycler; - - private final AtomicLong creatCounter; - - private final AtomicLong cycleCounter; - - public ObjectPool(Class clazz, Consumer prepare, Predicate recycler) { - this(2, clazz, prepare, recycler); - } - - public ObjectPool(int max, Class clazz, Consumer prepare, Predicate recycler) { - this(max, Creator.create(clazz), prepare, recycler); - } - - public ObjectPool(Creator creator, Consumer prepare, Predicate recycler) { - this(2, creator, prepare, recycler); - } - - public ObjectPool(int max, Creator creator, Consumer prepare, Predicate recycler) { - this(null, null, max, creator, prepare, recycler); - } - - public ObjectPool(AtomicLong creatCounter, AtomicLong cycleCounter, int max, Creator creator, Consumer prepare, Predicate recycler) { - this.creatCounter = creatCounter; - this.cycleCounter = cycleCounter; - this.creator = creator; - this.prepare = prepare; - this.recycler = recycler; - this.queue = new LinkedBlockingQueue(Math.max(Runtime.getRuntime().availableProcessors() * 2, max)); - this.debug = logger.isLoggable(Level.FINER); - } - - public void setCreator(Creator creator) { - this.creator = creator; - } - - @Override - public T get() { - T result = queue.poll(); - if (result == null) { - if (creatCounter != null) creatCounter.incrementAndGet(); - result = this.creator.create(); - } - if (prepare != null) prepare.accept(result); - return result; - } - - public void offer(final T e) { - if (e != null && recycler.test(e)) { - if (cycleCounter != null) cycleCounter.incrementAndGet(); - if (debug) { - for (T t : queue) { - if (t == e) { - logger.log(Level.WARNING, "[" + Thread.currentThread().getName() + "] repeat offer the same object(" + e + ")", new Exception()); - return; - } - } - } - queue.offer(e); - } - } - - public long getCreatCount() { - return creatCounter.longValue(); - } - - public long getCycleCount() { - return cycleCounter.longValue(); - } -} diff --git a/src/com/wentch/redkale/util/Reproduce.java b/src/com/wentch/redkale/util/Reproduce.java deleted file mode 100644 index 8282e4580..000000000 --- a/src/com/wentch/redkale/util/Reproduce.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.wentch.redkale.util; - -import java.lang.reflect.Modifier; -import java.util.function.Predicate; -import static jdk.internal.org.objectweb.asm.Opcodes.*; -import jdk.internal.org.objectweb.asm.*; - -public interface Reproduce { - - public D copy(D dest, S src); - - public static Reproduce create(final Class destClass, final Class srcClass) { - return create(destClass, srcClass, null); - } - - @SuppressWarnings("unchecked") - public static Reproduce create(final Class destClass, final Class srcClass, final Predicate columnPredicate) { - // ------------------------------------------------------------------------------ - final String supDynName = Reproduce.class.getName().replace('.', '/'); - final String destName = destClass.getName().replace('.', '/'); - final String srcName = srcClass.getName().replace('.', '/'); - final String destDesc = Type.getDescriptor(destClass); - final String srcDesc = Type.getDescriptor(srcClass); - String newDynName = supDynName + "Dyn_" + destClass.getSimpleName() + "_" + srcClass.getSimpleName(); - ClassLoader loader = Reproduce.class.getClassLoader(); - if (String.class.getClassLoader() != destClass.getClassLoader()) { - loader = destClass.getClassLoader(); - newDynName = destName + "_Dyn" + Reproduce.class.getSimpleName() + "_" + srcClass.getSimpleName(); - } - try { - return (Reproduce) Class.forName(newDynName.replace('/', '.')).newInstance(); - } catch (Exception ex) { - } - // ------------------------------------------------------------------------------ - ClassWriter cw = new ClassWriter(0); - FieldVisitor fv; - MethodVisitor mv; - AnnotationVisitor av0; - - cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;L" + supDynName + "<" + destDesc + srcDesc + ">;", "java/lang/Object", new String[]{supDynName}); - - { // 构造函数 - mv = (cw.visitMethod(ACC_PUBLIC, "", "()V", null, null)); - //mv.setDebug(true); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - { - mv = (cw.visitMethod(ACC_PUBLIC, "copy", "(" + destDesc + srcDesc + ")" + destDesc, null, null)); - //mv.setDebug(true); - - for (java.lang.reflect.Field field : srcClass.getFields()) { - if (Modifier.isStatic(field.getModifiers())) continue; - if (Modifier.isFinal(field.getModifiers())) continue; - if (!Modifier.isPublic(field.getModifiers())) continue; - final String fname = field.getName(); - try { - if (!field.getType().equals(destClass.getField(fname).getType())) continue; - if (!columnPredicate.test(fname)) continue; - } catch (Exception e) { - continue; - } - mv.visitVarInsn(ALOAD, 1); - mv.visitVarInsn(ALOAD, 2); - String td = Type.getDescriptor(field.getType()); - mv.visitFieldInsn(GETFIELD, srcName, fname, td); - mv.visitFieldInsn(PUTFIELD, destName, fname, td); - } - - for (java.lang.reflect.Method getter : srcClass.getMethods()) { - if (Modifier.isStatic(getter.getModifiers())) continue; - if (getter.getParameterCount() > 0) continue; - if ("getClass".equals(getter.getName())) continue; - if (!getter.getName().startsWith("get") && !getter.getName().startsWith("is")) continue; - java.lang.reflect.Method setter; - boolean is = getter.getName().startsWith("is"); - try { - setter = destClass.getMethod(getter.getName().replaceFirst(is ? "is" : "get", "set"), getter.getReturnType()); - if (columnPredicate != null) { - String col = setter.getName().substring(3); - if (col.length() < 2 || Character.isLowerCase(col.charAt(1))) { - char[] cs = col.toCharArray(); - cs[0] = Character.toLowerCase(cs[0]); - col = new String(cs); - } - if (!columnPredicate.test(col)) continue; - } - } catch (Exception e) { - continue; - } - mv.visitVarInsn(ALOAD, 1); - mv.visitVarInsn(ALOAD, 2); - mv.visitMethodInsn(INVOKEVIRTUAL, srcName, getter.getName(), Type.getMethodDescriptor(getter), false); - mv.visitMethodInsn(INVOKEVIRTUAL, destName, setter.getName(), Type.getMethodDescriptor(setter), false); - } - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ARETURN); - mv.visitMaxs(3, 3); - mv.visitEnd(); - } - { - mv = (cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "copy", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null)); - //mv.setDebug(true); - mv.visitVarInsn(ALOAD, 0); - mv.visitVarInsn(ALOAD, 1); - mv.visitTypeInsn(CHECKCAST, destName); - mv.visitVarInsn(ALOAD, 2); - mv.visitTypeInsn(CHECKCAST, srcName); - mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "copy", "(" + destDesc + srcDesc + ")" + destDesc, false); - mv.visitInsn(ARETURN); - mv.visitMaxs(3, 3); - mv.visitEnd(); - } - cw.visitEnd(); - // ------------------------------------------------------------------------------ - byte[] bytes = cw.toByteArray(); - Class creatorClazz = new ClassLoader(loader) { - public final Class loadClass(String name, byte[] b) { - return defineClass(name, b, 0, b.length); - } - }.loadClass(newDynName.replace('/', '.'), bytes); - try { - return (Reproduce) creatorClazz.newInstance(); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - -} diff --git a/src/com/wentch/redkale/util/ResourceFactory.java b/src/com/wentch/redkale/util/ResourceFactory.java deleted file mode 100644 index bf909833b..000000000 --- a/src/com/wentch/redkale/util/ResourceFactory.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.lang.reflect.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.logging.*; -import java.util.regex.*; -import javax.annotation.*; - -/** - * 如果Resource(name = "$") 表示资源name采用所属对象的name - * - * @author zhangjx - */ -@SuppressWarnings("unchecked") -public final class ResourceFactory { - - public static final String RESOURCE_PARENT_NAME = "$"; - - private static final Logger logger = Logger.getLogger(ResourceFactory.class.getSimpleName()); - - private final ResourceFactory parent; - - private static final ResourceFactory instance = new ResourceFactory(null); - - private final ConcurrentHashMap interceptmap = new ConcurrentHashMap<>(); - - private final ConcurrentHashMap, ConcurrentHashMap> store = new ConcurrentHashMap<>(); - - private final ConcurrentHashMap> gencstore = new ConcurrentHashMap<>(); - - private ResourceFactory(ResourceFactory parent) { - this.parent = parent; - } - - public static ResourceFactory root() { - return instance; - } - - public ResourceFactory createChild() { - return new ResourceFactory(this); - } - - public void release() { - this.store.clear(); - } - - public void register(final Class clazz, final Object rs) { - register("", clazz, rs); - } - - public void register(final Object rs) { - if (rs != null) register("", rs.getClass(), rs); - } - - public void add(final Type clazz, final Intercepter rs) { - if (clazz == null || rs == null) return; - interceptmap.put(clazz, rs); - } - - public void register(final String name, final Object rs) { - register(name, rs.getClass(), rs); - } - - public void register(final String name, final Class clazz, final A rs) { - ConcurrentHashMap map = this.store.get(clazz); - if (map == null) { - ConcurrentHashMap sub = new ConcurrentHashMap<>(); - sub.put(name, rs); - store.put(clazz, sub); - } else { - map.put(name, rs); - } - } - - public void register(final String name, final Type clazz, final A rs) { - if (clazz instanceof Class) { - register(name, (Class) clazz, rs); - return; - } - ConcurrentHashMap map = this.gencstore.get(clazz); - if (map == null) { - ConcurrentHashMap sub = new ConcurrentHashMap<>(); - sub.put(name, rs); - gencstore.put(clazz, sub); - } else { - map.put(name, rs); - } - } - - public A find(Class clazz) { - return find("", clazz); - } - - public A find(String name, Type clazz) { - Map map = this.gencstore.get(clazz); - if (map != null) { - A rs = (A) map.get(name); - if (rs != null) return rs; - } - if (parent != null) return parent.find(name, clazz); - return null; - } - - public A find(String name, Class clazz) { - Map map = this.store.get(clazz); - if (map != null) { - A rs = (A) map.get(name); - if (rs != null) return rs; - } - if (parent != null) return parent.find(name, clazz); - return null; - } - - public A findChild(String name, Class clazz) { - A rs = find(name, clazz); - if (rs != null) return rs; - Optional, ConcurrentHashMap>> opt = this.store.entrySet().stream() - .filter(x -> clazz.isAssignableFrom(x.getKey()) && x.getValue().containsKey(name)) - .findFirst(); - return opt.isPresent() ? (A) opt.get().getValue().get(name) : null; - } - - public Map find(final Pattern reg, Class clazz, A exclude) { - Map result = new LinkedHashMap<>(); - load(reg, clazz, exclude, result); - return result; - } - - private void load(final Pattern reg, Class clazz, final A exclude, final Map result) { - ConcurrentHashMap map = this.store.get(clazz); - if (map != null) { - map.forEach((x, y) -> { - if (y != exclude && reg.matcher(x).find() && result.get(x) == null) result.put(x, (A) y); - }); - } - if (parent != null) parent.load(reg, clazz, exclude, result); - } - - public boolean inject(final Object src) { - return inject(src, null); - } - - public boolean inject(final Object src, final T attachment) { - return inject(src, attachment, new ArrayList<>()); - } - - private boolean inject(final Object src, final T attachment, final List list) { - if (src == null) return false; - try { - list.add(src); - Class clazz = src.getClass(); - do { - for (Field field : clazz.getDeclaredFields()) { - if (Modifier.isStatic(field.getModifiers())) continue; - field.setAccessible(true); - final Class classtype = field.getType(); - final Type genctype = field.getGenericType(); - Resource rc = field.getAnnotation(Resource.class); - if (rc == null) { - boolean flag = true; - Object ns = field.get(src); - for (Object o : list) { - if (o == ns) { - flag = false; - break; - } - } - if (ns == null) continue; - if (ns.getClass().isPrimitive() || ns.getClass().isArray() || ns.getClass().getName().startsWith("java")) continue; - if (flag) this.inject(ns, attachment, list); - continue; - } - if (Modifier.isFinal(field.getModifiers())) continue; - final String rcname = (rc.name().equals(RESOURCE_PARENT_NAME) && src instanceof Nameable) ? ((Nameable) src).name() : rc.name(); - Object rs = genctype == classtype ? null : find(rcname, genctype); - if (rs == null) { - if (Map.class.isAssignableFrom(classtype)) { - rs = find(Pattern.compile(rcname.isEmpty() ? ".*" : rcname), (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[1], src); - } else if (rcname.startsWith("property.")) { - rs = find(rcname, String.class); - } else { - rs = find(rcname, classtype); - } - } - if (rs == null) { - Intercepter it = findIntercepter(field.getGenericType(), field); - if (it != null) it.invoke(this, src, field, attachment); - continue; - } - if (!rs.getClass().isPrimitive() && classtype.isPrimitive()) { - if (classtype == int.class) { - rs = Integer.decode(rs.toString()); - } else if (classtype == long.class) { - rs = Long.decode(rs.toString()); - } else if (classtype == short.class) { - rs = Short.decode(rs.toString()); - } else if (classtype == boolean.class) { - rs = "true".equalsIgnoreCase(rs.toString()); - } else if (classtype == byte.class) { - rs = Byte.decode(rs.toString()); - } else if (classtype == float.class) { - rs = Float.parseFloat(rs.toString()); - } else if (classtype == double.class) { - rs = Double.parseDouble(rs.toString()); - } - } - field.set(src, rs); - } - } while ((clazz = clazz.getSuperclass()) != Object.class); - return true; - } catch (Exception ex) { - logger.log(Level.FINER, "inject " + src + " error", ex); - return false; - } - } - - private Intercepter findIntercepter(Type ft, Field field) { - Intercepter it = this.interceptmap.get(ft); - if (it != null) return it; - Class c = field.getType(); - for (Map.Entry en : this.interceptmap.entrySet()) { - Type t = en.getKey(); - if (t == ft) return en.getValue(); - if (t instanceof Class && (((Class) t)).isAssignableFrom(c)) return en.getValue(); - } - return parent == null ? null : parent.findIntercepter(ft, field); - } - - public static interface Intercepter { - - public void invoke(ResourceFactory factory, Object src, Field field, Object attachment); - } - -} diff --git a/src/com/wentch/redkale/util/SelectColumn.java b/src/com/wentch/redkale/util/SelectColumn.java deleted file mode 100644 index 991b5f0d9..000000000 --- a/src/com/wentch/redkale/util/SelectColumn.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.util.*; -import java.util.function.*; -import java.util.regex.*; - -/** - * - * @author zhangjx - */ -public class SelectColumn implements Predicate { - - private Pattern[] patterns; - - private String[] columns; - - private boolean excludable; //是否排除 - - public SelectColumn() { - } - - protected SelectColumn(final String[] columns0, final boolean excludable) { - this.excludable = excludable; - final int len = columns0.length; - if (len < 1) return; - Pattern[] regs = null; - String[] cols = null; - int regcount = 0; - int colcount = 0; - for (String col : columns0) { - boolean reg = false; - for (int i = 0; i < col.length(); i++) { - char ch = col.charAt(i); - if (ch == '^' || ch == '$' || ch == '*' || ch == '?' || ch == '+' || ch == '[' || ch == '(') { - reg = true; - break; - } - } - if (reg) { - if (regs == null) regs = new Pattern[len]; - regs[regcount++] = Pattern.compile(col); - } else { - if (cols == null) cols = new String[len]; - cols[colcount++] = col; - } - } - if (regs != null) { - if (regcount == len) { - this.patterns = regs; - } else { - this.patterns = Arrays.copyOf(regs, regcount); - } - } - if (cols != null) { - if (colcount == len) { - this.columns = cols; - } else { - this.columns = Arrays.copyOf(cols, colcount); - } - } - } - - /** - * class中的字段名 - * - * @param columns - * @return - */ - public static SelectColumn createIncludes(String... columns) { - return new SelectColumn(columns, false); - } - - /** - * class中的字段名 - * - * @param columns - * @return - */ - public static SelectColumn createExcludes(String... columns) { - return new SelectColumn(columns, true); - } - - @Override - public boolean test(final String column) { - if (this.columns != null) { - for (String col : this.columns) { - if (col.equalsIgnoreCase(column)) return !excludable; - } - } - if (this.patterns != null) { - for (Pattern reg : this.patterns) { - if (reg.matcher(column).find()) return !excludable; - } - } - return excludable; - } - - public String[] getColumns() { - return columns; - } - - public void setColumns(String[] columns) { - this.columns = columns; - } - - public boolean isExcludable() { - return excludable; - } - - public void setExcludable(boolean excludable) { - this.excludable = excludable; - } - - public Pattern[] getPatterns() { - return patterns; - } - - public void setPatterns(Pattern[] patterns) { - this.patterns = patterns; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(getClass().getSimpleName()).append("{excludable=").append(excludable); - if (columns != null) sb.append(", columns=").append(Arrays.toString(columns)); - if (patterns != null) sb.append(", patterns=").append(Arrays.toString(patterns)); - return sb.append('}').toString(); - } - -} diff --git a/src/com/wentch/redkale/util/Sheet.java b/src/com/wentch/redkale/util/Sheet.java deleted file mode 100644 index 9d83e82d6..000000000 --- a/src/com/wentch/redkale/util/Sheet.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.util.*; - -/** - * - * @author zhangjx - * @param - */ -@SuppressWarnings("unchecked") -public class Sheet implements java.io.Serializable { - - private long total = -1; - - private Collection rows; - - public Sheet() { - super(); - } - - public Sheet(int total, Collection data) { - this((long) total, data); - } - - public Sheet(long total, Collection data) { - this.total = total; - this.rows = (Collection) data; - } - - public static Sheet asSheet(Collection data) { - return data == null ? new Sheet<>() : new Sheet<>(data.size(), data); - } - - public Sheet copyTo(Sheet copy) { - if (copy == null) return copy; - copy.total = this.total; - if (this.getRows() != null) { - copy.setRows(new ArrayList<>(this.getRows())); - } else { - copy.rows = null; - } - return copy; - } - - /** - * 判断数据列表是否为空 - * - * @return - */ - public boolean isEmpty() { - return this.rows == null || this.rows.isEmpty(); - } - - @Override - public String toString() { - return "Sheet[total=" + this.total + ", rows=" + this.rows + "]"; - } - - public long getTotal() { - return this.total; - } - - public void setTotal(long total) { - this.total = total; - } - - public Collection getRows() { - return this.rows; - } - - public List list() { - return list(false); - } - - public List list(boolean created) { - if (this.rows == null) return created ? new ArrayList<>() : null; - return (this.rows instanceof List) ? (List) this.rows : new ArrayList<>(this.rows); - } - - public void setRows(Collection data) { - this.rows = (Collection) data; - } -} diff --git a/src/com/wentch/redkale/util/TypeToken.java b/src/com/wentch/redkale/util/TypeToken.java deleted file mode 100644 index 63b67ed02..000000000 --- a/src/com/wentch/redkale/util/TypeToken.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; - -/** - * - * @author zhangjx - * @param - */ -public abstract class TypeToken { - - private final Type type; - - public TypeToken() { - type = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; - } - - public final Type getType() { - return type; - } -} diff --git a/src/com/wentch/redkale/util/Utility.java b/src/com/wentch/redkale/util/Utility.java deleted file mode 100644 index 29d76c275..000000000 --- a/src/com/wentch/redkale/util/Utility.java +++ /dev/null @@ -1,517 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.util; - -import java.io.*; -import java.lang.reflect.Field; -import java.net.*; -import java.nio.ByteBuffer; -import java.nio.charset.*; -import java.time.*; -import java.util.*; -import javax.net.ssl.*; - -/** - * - * @author zhangjx - */ -public final class Utility { - - private static final String format = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL"; - - private static final Charset UTF_8 = Charset.forName("UTF-8"); - - private static final char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - - private static final sun.misc.Unsafe UNSAFE; - - private static final long strvaloffset; - - private static final long sbvaloffset; - - private static final javax.net.ssl.SSLContext DEFAULTSSL_CONTEXT; - - static { - sun.misc.Unsafe usafe = null; - long fd1 = 0L; - long fd2 = 0L; - try { - Field safeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); - safeField.setAccessible(true); - usafe = (sun.misc.Unsafe) safeField.get(null); - fd1 = usafe.objectFieldOffset(String.class.getDeclaredField("value")); - fd2 = usafe.objectFieldOffset(StringBuilder.class.getSuperclass().getDeclaredField("value")); - } catch (Exception e) { - throw new RuntimeException(e); //不可能会发生 - } - UNSAFE = usafe; - strvaloffset = fd1; - sbvaloffset = fd2; - - try { - DEFAULTSSL_CONTEXT = javax.net.ssl.SSLContext.getInstance("SSL"); - DEFAULTSSL_CONTEXT.init(null, new javax.net.ssl.TrustManager[]{new javax.net.ssl.X509TrustManager() { - @Override - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return null; - } - - @Override - public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { - } - - @Override - public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { - } - }}, null); - } catch (Exception e) { - throw new RuntimeException(e); //不可能会发生 - } - } - - private Utility() { - } - - public static String now() { - return String.format(format, System.currentTimeMillis()); - } - - public static void println(String string, ByteBuffer buffer) { - if (buffer == null || !buffer.hasRemaining()) return; - byte[] bytes = new byte[buffer.remaining()]; - buffer.get(bytes); - buffer.flip(); - println(string, bytes); - } - - public static void println(String string, byte... bytes) { - if (bytes == null) return; - StringBuilder sb = new StringBuilder(); - if (string != null) sb.append(string); - sb.append(bytes.length).append(".["); - boolean last = false; - for (byte b : bytes) { - if (last) sb.append(','); - int v = b & 0xff; - if (v < 16) sb.append('0'); - sb.append(Integer.toHexString(v)); - last = true; - } - sb.append(']'); - (System.out).println(sb); - } - - /** - * 返回本机的第一个内网IPv4地址, 没有则返回null - *

- * @return - */ - public static InetAddress localInetAddress() { - InetAddress back = null; - try { - Enumeration nifs = NetworkInterface.getNetworkInterfaces(); - while (nifs.hasMoreElements()) { - NetworkInterface nif = nifs.nextElement(); - if (!nif.isUp()) continue; - Enumeration eis = nif.getInetAddresses(); - while (eis.hasMoreElements()) { - InetAddress ia = eis.nextElement(); - if (ia.isLoopbackAddress()) back = ia; - if (ia.isSiteLocalAddress()) return ia; - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return back; - } - - public static int today() { - java.time.LocalDate today = java.time.LocalDate.now(); - return today.getYear() * 10000 + today.getMonthValue() * 100 + today.getDayOfMonth(); - } - - //时间点所在星期的周一 - public static long monday(long time) { - ZoneId zid = ZoneId.systemDefault(); - Instant instant = Instant.ofEpochMilli(time); - LocalDate ld = instant.atZone(zid).toLocalDate(); - ld = ld.minusDays(ld.getDayOfWeek().getValue() - 1); - return ld.atStartOfDay(zid).toInstant().toEpochMilli(); - } - - //时间点所在星期的周日 - public static long sunday(long time) { - ZoneId zid = ZoneId.systemDefault(); - Instant instant = Instant.ofEpochMilli(time); - LocalDate ld = instant.atZone(zid).toLocalDate(); - ld = ld.plusDays(7 - ld.getDayOfWeek().getValue()); - return ld.atStartOfDay(zid).toInstant().toEpochMilli(); - } - - //时间点所在月份的1号 - public static long monthFirstDay(long time) { - ZoneId zid = ZoneId.systemDefault(); - Instant instant = Instant.ofEpochMilli(time); - LocalDate ld = instant.atZone(zid).toLocalDate().withDayOfMonth(1); - return ld.atStartOfDay(zid).toInstant().toEpochMilli(); - } - - public static String binToHexString(byte[] bytes) { - return new String(binToHex(bytes)); - } - - public static char[] binToHex(byte[] bytes) { - return binToHex(bytes, 0, bytes.length); - } - - public static String binToHexString(byte[] bytes, int offset, int len) { - return new String(binToHex(bytes, offset, len)); - } - - public static char[] binToHex(byte[] bytes, int offset, int len) { - final char[] sb = new char[len * 2]; - final int end = offset + len; - int index = 0; - final char[] hexs = hex; - for (int i = offset; i < end; i++) { - byte b = bytes[i]; - sb[index++] = (hexs[((b >> 4) & 0xF)]); - sb[index++] = hexs[((b) & 0xF)]; - } - return sb; - } - - public static byte[] hexToBin(CharSequence src) { - return hexToBin(src, 0, src.length()); - } - - public static byte[] hexToBin(CharSequence src, int offset, int len) { - final int size = (len + 1) / 2; - final byte[] bytes = new byte[size]; - final int end = offset + len; - String digits = "0123456789abcdef"; - for (int i = 0; i < size; i++) { - int ch1 = src.charAt(offset + i * 2); - if ('A' <= ch1 && 'F' >= ch1) ch1 = ch1 - 'A' + 'a'; - int ch2 = src.charAt(offset + i * 2 + 1); - if ('A' <= ch2 && 'F' >= ch2) ch2 = ch2 - 'A' + 'a'; - int pos1 = digits.indexOf(ch1); - if (pos1 < 0) throw new NumberFormatException(); - int pos2 = digits.indexOf(ch2); - if (pos2 < 0) throw new NumberFormatException(); - bytes[i] = (byte) (pos1 * 0x10 + pos2); - } - return bytes; - } - - public static byte[] hexToBin(char[] src) { - return hexToBin(src, 0, src.length); - } - - public static byte[] hexToBin(char[] src, int offset, int len) { - final int size = (len + 1) / 2; - final byte[] bytes = new byte[size]; - final int end = offset + len; - String digits = "0123456789abcdef"; - for (int i = 0; i < size; i++) { - int ch1 = src[offset + i * 2]; - if ('A' <= ch1 && 'F' >= ch1) ch1 = ch1 - 'A' + 'a'; - int ch2 = src[offset + i * 2 + 1]; - if ('A' <= ch2 && 'F' >= ch2) ch2 = ch2 - 'A' + 'a'; - int pos1 = digits.indexOf(ch1); - if (pos1 < 0) throw new NumberFormatException(); - int pos2 = digits.indexOf(ch2); - if (pos2 < 0) throw new NumberFormatException(); - bytes[i] = (byte) (pos1 * 0x10 + pos2); - } - return bytes; - } - - //----------------------------------------------------------------------------- - public static char[] decodeUTF8(final byte[] array) { - return decodeUTF8(array, 0, array.length); - } - - public static char[] decodeUTF8(final byte[] array, final int start, final int len) { - byte b; - int size = len; - final byte[] bytes = array; - final int limit = start + len; - for (int i = start; i < limit; i++) { - b = bytes[i]; - if ((b >> 5) == -2) { - size--; - } else if ((b >> 4) == -2) { - size -= 2; - } - } - final char[] text = new char[size]; - size = 0; - for (int i = start; i < limit;) { - b = bytes[i++]; - if (b >= 0) { - text[size++] = (char) b; - } else if ((b >> 5) == -2) { - text[size++] = (char) (((b << 6) ^ bytes[i++]) ^ (((byte) 0xC0 << 6) ^ ((byte) 0x80))); - } else if ((b >> 4) == -2) { - text[size++] = (char) ((b << 12) ^ (bytes[i++] << 6) ^ (bytes[i++] ^ (((byte) 0xE0 << 12) ^ ((byte) 0x80 << 6) ^ ((byte) 0x80)))); - } - } - return text; - } - - public static byte[] encodeUTF8(final String value) { - if (value == null) return new byte[0]; - return encodeUTF8((char[]) UNSAFE.getObject(value, strvaloffset)); - } - - public static byte[] encodeUTF8(final char[] array) { - return encodeUTF8(array, 0, array.length); - } - - public static byte[] encodeUTF8(final char[] text, final int start, final int len) { - char c; - int size = 0; - final char[] chars = text; - final int limit = start + len; - for (int i = start; i < limit; i++) { - c = chars[i]; - if (c < 0x80) { - size++; - } else if (c < 0x800) { - size += 2; - } else { - size += 3; - } - } - final byte[] bytes = new byte[size]; - size = 0; - for (int i = start; i < limit; i++) { - c = chars[i]; - if (c < 0x80) { - bytes[size++] = (byte) c; - } else if (c < 0x800) { - bytes[size++] = (byte) (0xc0 | (c >> 6)); - bytes[size++] = (byte) (0x80 | (c & 0x3f)); - } else { - bytes[size++] = (byte) (0xe0 | ((c >> 12))); - bytes[size++] = (byte) (0x80 | ((c >> 6) & 0x3f)); - bytes[size++] = (byte) (0x80 | (c & 0x3f)); - } - } - return bytes; - } - - public static char[] charArray(String value) { - return value == null ? null : (char[]) UNSAFE.getObject(value, strvaloffset); - } - - public static char[] charArray(StringBuilder value) { - return value == null ? null : (char[]) UNSAFE.getObject(value, sbvaloffset); - } - - public static ByteBuffer encodeUTF8(final ByteBuffer buffer, final char[] array) { - return encodeUTF8(buffer, array, 0, array.length); - } - - public static ByteBuffer encodeUTF8(final ByteBuffer buffer, int bytesLength, final char[] array) { - return encodeUTF8(buffer, bytesLength, array, 0, array.length); - } - - public static int encodeUTF8Length(String value) { - if (value == null) return -1; - return encodeUTF8Length((char[]) UNSAFE.getObject(value, strvaloffset)); - } - - public static int encodeUTF8Length(final char[] text) { - return encodeUTF8Length(text, 0, text.length); - } - - public static int encodeUTF8Length(final char[] text, final int start, final int len) { - char c; - int size = 0; - final char[] chars = text; - final int limit = start + len; - for (int i = start; i < limit; i++) { - c = chars[i]; - size += (c < 0x80 ? 1 : (c < 0x800 ? 2 : 3)); - } - return size; - } - - /** - * 将两个数字组装成一个long - *

- * @param high - * @param low - * @return - */ - public static long merge(long high, long low) { - return high << 32 | low; - } - - public static ByteBuffer encodeUTF8(final ByteBuffer buffer, final char[] text, final int start, final int len) { - return encodeUTF8(buffer, encodeUTF8Length(text, start, len), text, start, len); - } - - public static ByteBuffer encodeUTF8(final ByteBuffer buffer, int bytesLength, final char[] text, final int start, final int len) { - char c; - char[] chars = text; - final int limit = start + len; - int remain = buffer.remaining(); - final ByteBuffer buffer2 = remain >= bytesLength ? null : ByteBuffer.allocate(bytesLength - remain + 3); //最差情况buffer最后两byte没有填充 - ByteBuffer buf = buffer; - for (int i = start; i < limit; i++) { - c = chars[i]; - if (c < 0x80) { - if (buf.remaining() < 1) buf = buffer2; - buf.put((byte) c); - } else if (c < 0x800) { - if (buf.remaining() < 2) buf = buffer2; - buf.put((byte) (0xc0 | (c >> 6))); - buf.put((byte) (0x80 | (c & 0x3f))); - } else { - if (buf.remaining() < 3) buf = buffer2; - buf.put((byte) (0xe0 | ((c >> 12)))); - buf.put((byte) (0x80 | ((c >> 6) & 0x3f))); - buf.put((byte) (0x80 | (c & 0x3f))); - } - } - if (buffer2 != null) buffer2.flip(); - return buffer2; - } - - //----------------------------------------------------------------------------- - public static javax.net.ssl.SSLContext getDefaultSSLContext() { - return DEFAULTSSL_CONTEXT; - } - - public static Socket createDefaultSSLSocket(InetSocketAddress address) throws IOException { - return createDefaultSSLSocket(address.getAddress(), address.getPort()); - } - - public static Socket createDefaultSSLSocket(InetAddress host, int port) throws IOException { - Socket socket = DEFAULTSSL_CONTEXT.getSocketFactory().createSocket(host, port); - - return socket; - } - - public static String postHttpContent(String url) throws IOException { - return remoteHttpContent(null, "POST", url, null, null).toString("UTF-8"); - } - - public static String postHttpContent(String url, String body) throws IOException { - return remoteHttpContent(null, "POST", url, null, body).toString("UTF-8"); - } - - public static String postHttpContent(String url, Map headers, String body) throws IOException { - return remoteHttpContent(null, "POST", url, headers, body).toString("UTF-8"); - } - - public static String postHttpContent(SSLContext ctx, String url) throws IOException { - return remoteHttpContent(ctx, "POST", url, null, null).toString("UTF-8"); - } - - public static String postHttpContent(SSLContext ctx, String url, String body) throws IOException { - return remoteHttpContent(ctx, "POST", url, null, body).toString("UTF-8"); - } - - public static String postHttpContent(SSLContext ctx, String url, Map headers, String body) throws IOException { - return remoteHttpContent(ctx, "POST", url, headers, body).toString("UTF-8"); - } - - public static byte[] postHttpBytesContent(String url) throws IOException { - return remoteHttpContent(null, "POST", url, null, null).toByteArray(); - } - - public static byte[] postHttpBytesContent(SSLContext ctx, String url) throws IOException { - return remoteHttpContent(ctx, "POST", url, null, null).toByteArray(); - } - - public static byte[] postHttpBytesContent(String url, Map headers, String body) throws IOException { - return remoteHttpContent(null, "POST", url, headers, body).toByteArray(); - } - - public static byte[] postHttpBytesContent(SSLContext ctx, String url, Map headers, String body) throws IOException { - return remoteHttpContent(ctx, "POST", url, headers, body).toByteArray(); - } - - public static String getHttpContent(String url) throws IOException { - return remoteHttpContent(null, "GET", url, null, null).toString("UTF-8"); - } - - public static String getHttpContent(SSLContext ctx, String url) throws IOException { - return remoteHttpContent(ctx, "GET", url, null, null).toString("UTF-8"); - } - - public static String getHttpContent(SSLContext ctx, String url, Map headers, String body) throws IOException { - return remoteHttpContent(ctx, "GET", url, headers, body).toString("UTF-8"); - } - - public static String getHttpContent(String url, Map headers, String body) throws IOException { - return remoteHttpContent(null, "GET", url, headers, body).toString("UTF-8"); - } - - public static byte[] getHttpBytesContent(String url) throws IOException { - return remoteHttpContent(null, "GET", url, null, null).toByteArray(); - } - - public static byte[] getHttpBytesContent(SSLContext ctx, String url) throws IOException { - return remoteHttpContent(ctx, "GET", url, null, null).toByteArray(); - } - - public static byte[] getHttpBytesContent(String url, Map headers, String body) throws IOException { - return remoteHttpContent(null, "GET", url, headers, body).toByteArray(); - } - - public static byte[] getHttpBytesContent(SSLContext ctx, String url, Map headers, String body) throws IOException { - return remoteHttpContent(ctx, "GET", url, headers, body).toByteArray(); - } - - protected static ByteArrayOutputStream remoteHttpContent(SSLContext ctx, String method, String url, Map headers, String body) throws IOException { - HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); - conn.setConnectTimeout(3000); - conn.setReadTimeout(3000); - if (conn instanceof HttpsURLConnection) ((HttpsURLConnection) conn).setSSLSocketFactory((ctx == null ? DEFAULTSSL_CONTEXT : ctx).getSocketFactory()); - conn.setRequestMethod(method); - if (headers != null) headers.forEach((x, y) -> conn.setRequestProperty(x, y)); - if (body != null) { - conn.setDoInput(true); - conn.setDoOutput(true); - conn.getOutputStream().write(body.getBytes(UTF_8)); - } - conn.connect(); - int rs = conn.getResponseCode(); - if (rs == 301 || rs == 302) { - String newurl = conn.getHeaderField("Location"); - conn.disconnect(); - return remoteHttpContent(ctx, method, newurl, headers, body); - } - InputStream in = conn.getInputStream(); - ByteArrayOutputStream out = new ByteArrayOutputStream(1024); - byte[] bytes = new byte[1024]; - int pos; - while ((pos = in.read(bytes)) != -1) { - out.write(bytes, 0, pos); - } - conn.disconnect(); - return out; - } - - public static String read(InputStream in) throws IOException { - return read(in, "UTF-8"); - } - - public static String read(InputStream in, String charsetName) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(1024); - byte[] bytes = new byte[1024]; - int pos; - while ((pos = in.read(bytes)) != -1) { - out.write(bytes, 0, pos); - } - return charsetName == null ? out.toString() : out.toString(charsetName); - } -} diff --git a/src/com/wentch/redkale/watch/WatchFactory.java b/src/com/wentch/redkale/watch/WatchFactory.java deleted file mode 100644 index db5f4a5a4..000000000 --- a/src/com/wentch/redkale/watch/WatchFactory.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.watch; - -import java.lang.ref.WeakReference; -import java.lang.reflect.*; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.function.LongSupplier; - -/** - * - * @author zhangjx - */ -public final class WatchFactory { - - private static final WatchFactory instance = new WatchFactory(null); - - private final List> beans = new CopyOnWriteArrayList<>(); - - private final WatchFactory parent; - - private WatchFactory(WatchFactory parent) { - this.parent = parent; - } - - public void register(WatchNode bean) { - if (bean != null) beans.add(new WeakReference<>(bean)); - } - - public static WatchFactory root() { - return instance; - } - - public WatchFactory createChild() { - return new WatchFactory(this); - } - - public WatchNumber createWatchNumber(String name) { - return createWatchNumber(name, "", false, 0); - } - - public WatchNumber createWatchNumber(String name, boolean interval) { - return createWatchNumber(name, "", interval, 0); - } - - public WatchNumber createWatchNumber(String name, String description) { - return createWatchNumber(name, description, false, 0); - } - - public WatchNumber createWatchNumber(String name, String description, long v) { - return createWatchNumber(name, description, false, 0); - } - - public WatchNumber createWatchNumber(String name, String description, boolean interval) { - return createWatchNumber(name, description, interval, 0); - } - - public WatchNumber createWatchNumber(String name, String description, boolean interval, long v) { - WatchNumber bean = new WatchNumber(name, description, interval, v); - register(bean); - return bean; - } - - public void register(String name, LongSupplier supplier) { - register(name, "", supplier); - } - - public void register(String name, String description, LongSupplier supplier) { - register(new WatchSupplier(name, description, supplier)); - } - - public boolean inject(final Object src) { - return inject(src, new ArrayList<>()); - } - - private boolean inject(final Object src, final List list) { - if (src == null) return false; - try { - list.add(src); - Class clazz = src.getClass(); - do { - for (Field field : clazz.getDeclaredFields()) { - if (Modifier.isFinal(field.getModifiers())) continue; - field.setAccessible(true); - final Class type = field.getType(); - Watchable wo = field.getAnnotation(Watchable.class); - - } - } while ((clazz = clazz.getSuperclass()) != Object.class); - return true; - } catch (Exception ex) { - return false; - } - } -} diff --git a/src/com/wentch/redkale/watch/WatchNode.java b/src/com/wentch/redkale/watch/WatchNode.java deleted file mode 100644 index cabf81701..000000000 --- a/src/com/wentch/redkale/watch/WatchNode.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.watch; - -/** - * - * @author zhangjx - */ -public interface WatchNode { - - public String getName(); - - public String getDescription(); - - public long getValue(); - - public boolean isInterval(); -} diff --git a/src/com/wentch/redkale/watch/WatchNumber.java b/src/com/wentch/redkale/watch/WatchNumber.java deleted file mode 100644 index 5ef8fff43..000000000 --- a/src/com/wentch/redkale/watch/WatchNumber.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.watch; - -import java.util.concurrent.atomic.*; - -/** - * - * @author zhangjx - */ -public final class WatchNumber extends AtomicLong implements WatchNode { - - private final boolean interval; - - private final String name; - - private final String description; - - WatchNumber(String name, String description, boolean interval, long v) { - this.name = name; - this.description = description; - this.interval = interval; - this.set(v); - } - - @Override - public String getName() { - return name; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public long getValue() { - return super.longValue(); - } - - @Override - public boolean isInterval() { - return interval; - } - -} diff --git a/src/com/wentch/redkale/watch/WatchSupplier.java b/src/com/wentch/redkale/watch/WatchSupplier.java deleted file mode 100644 index 8f1dd045f..000000000 --- a/src/com/wentch/redkale/watch/WatchSupplier.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.watch; - -import java.util.function.LongSupplier; - -/** - * - * @author zhangjx - */ -public final class WatchSupplier implements WatchNode { - - private final String name; - - private final String description; - - private final LongSupplier supplier; - - WatchSupplier(String name, String description, LongSupplier supplier) { - this.name = name; - this.description = description; - this.supplier = supplier; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String getDescription() { - return this.description; - } - - @Override - public long getValue() { - return supplier == null ? Long.MIN_VALUE : supplier.getAsLong(); - } - - @Override - public boolean isInterval() { - return false; - } -} diff --git a/src/com/wentch/redkale/watch/Watchable.java b/src/com/wentch/redkale/watch/Watchable.java deleted file mode 100644 index 1d07fd2d0..000000000 --- a/src/com/wentch/redkale/watch/Watchable.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.watch; - -import java.lang.annotation.*; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * 该注解只能放在field类型为Collection, Map, 或者java.util.concurrent.atomic.AtomicXXX的Number类); - * - * @author zhangjx - */ -@Inherited -@Documented -@Target({FIELD}) -@Retention(RUNTIME) -public @interface Watchable { - - String name(); - - String description() default ""; - - /** - * 该值指明是不是只收集阶段数据, 而且被注解的字段只能被赋予java.util.concurrent.atomic.AtomicXXX的Number类型字段。 - * 例如收集每分钟的注册用户数, 就需要将interval设置true。 - * - * @return - */ - boolean interval() default false; -}