{"diffoscope-json-version": 1, "source1": "/input1", "source2": "/input2", "unified_diff": null, "details": [{"source1": "zipinfo {}", "source2": "zipinfo {}", "unified_diff": "@@ -1,8 +1,8 @@\n-Zip file size: 48391 bytes, number of entries: 42\n+Zip file size: 48627 bytes, number of entries: 42\n -rw-r--r--  2.0 unx       64 b- defN 20-Apr-01 08:04 META-INF/MANIFEST.MF\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 META-INF/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 org/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 org/apache/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 org/apache/dubbo/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 org/apache/dubbo/rpc/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/\n@@ -13,32 +13,32 @@\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 META-INF/dubbo/internal/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 META-INF/maven/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 META-INF/maven/org.apache.dubbo/\n drwxr-xr-x  2.0 unx        0 b- stor 20-Apr-01 08:04 META-INF/maven/org.apache.dubbo/dubbo-rpc-dubbo/\n -rw-r--r--  2.0 unx     3136 b- defN 20-Apr-01 08:04 META-INF/DEPENDENCIES\n -rw-r--r--  2.0 unx    11358 b- defN 20-Apr-01 08:04 META-INF/LICENSE\n -rw-r--r--  2.0 unx      172 b- defN 20-Apr-01 08:04 META-INF/NOTICE\n--rw-r--r--  2.0 unx    15943 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java\n--rw-r--r--  2.0 unx     6371 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java\n--rw-r--r--  2.0 unx     2232 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/Constants.java\n--rw-r--r--  2.0 unx     7990 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java\n--rw-r--r--  2.0 unx     7072 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java\n--rw-r--r--  2.0 unx    10983 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java\n--rw-r--r--  2.0 unx     2585 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboCodecSupport.java\n--rw-r--r--  2.0 unx     3102 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboCountCodec.java\n--rw-r--r--  2.0 unx     1457 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java\n--rw-r--r--  2.0 unx     8153 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java\n--rw-r--r--  2.0 unx    27447 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java\n--rw-r--r--  2.0 unx     1812 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolServer.java\n--rw-r--r--  2.0 unx     8140 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java\n--rw-r--r--  2.0 unx     6087 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java\n--rw-r--r--  2.0 unx     8744 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java\n--rw-r--r--  2.0 unx     5704 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/filter/TraceFilter.java\n--rw-r--r--  2.0 unx     2276 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/status/ServerStatusChecker.java\n--rw-r--r--  2.0 unx     2950 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/status/ThreadPoolStatusChecker.java\n+-rw-r--r--  2.0 unx    16261 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java\n+-rw-r--r--  2.0 unx     6554 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java\n+-rw-r--r--  2.0 unx     2303 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/Constants.java\n+-rw-r--r--  2.0 unx     8185 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java\n+-rw-r--r--  2.0 unx     7256 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java\n+-rw-r--r--  2.0 unx    11231 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java\n+-rw-r--r--  2.0 unx     2638 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboCodecSupport.java\n+-rw-r--r--  2.0 unx     3188 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboCountCodec.java\n+-rw-r--r--  2.0 unx     1501 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java\n+-rw-r--r--  2.0 unx     8336 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java\n+-rw-r--r--  2.0 unx    28133 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java\n+-rw-r--r--  2.0 unx     1874 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolServer.java\n+-rw-r--r--  2.0 unx     8409 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java\n+-rw-r--r--  2.0 unx     6298 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java\n+-rw-r--r--  2.0 unx     8947 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java\n+-rw-r--r--  2.0 unx     5831 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/filter/TraceFilter.java\n+-rw-r--r--  2.0 unx     2337 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/status/ServerStatusChecker.java\n+-rw-r--r--  2.0 unx     3017 b- defN 20-Apr-01 08:04 org/apache/dubbo/rpc/protocol/dubbo/status/ThreadPoolStatusChecker.java\n -rw-r--r--  2.0 unx      148 b- defN 20-Apr-01 08:04 META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker\n -rw-r--r--  2.0 unx       57 b- defN 20-Apr-01 08:04 META-INF/dubbo/internal/org.apache.dubbo.remoting.Codec2\n -rw-r--r--  2.0 unx      124 b- defN 20-Apr-01 08:04 META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter\n -rw-r--r--  2.0 unx       55 b- defN 20-Apr-01 08:04 META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol\n--rw-r--r--  2.0 unx     4028 b- defN 20-Apr-01 08:04 META-INF/maven/org.apache.dubbo/dubbo-rpc-dubbo/pom.xml\n+-rw-r--r--  2.0 unx     3916 b- defN 20-Apr-01 08:04 META-INF/maven/org.apache.dubbo/dubbo-rpc-dubbo/pom.xml\n -rw-r--r--  2.0 unx       70 b- defN 20-Apr-01 08:04 META-INF/maven/org.apache.dubbo/dubbo-rpc-dubbo/pom.properties\n-42 files, 148260 bytes uncompressed, 41497 bytes compressed:  72.0%\n+42 files, 151399 bytes uncompressed, 41733 bytes compressed:  72.4%\n"}, {"source1": "zipdetails --redact --scan --utc {}", "source2": "zipdetails --redact --scan --utc {}", "unified_diff": "@@ -335,1780 +335,1780 @@\n 16F5 Extract Zip Spec      14 (20) '2.0'\n 16F6 Extract OS            00 (0) 'MS-DOS'\n 16F7 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n 16F9 Compression Method    0008 (8) 'Deflated'\n 16FB Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-16FF CRC                   B7F8FDDA (3086548442)\n-1703 Compressed Size       00000EEE (3822)\n-1707 Uncompressed Size     00003E47 (15943)\n+16FF CRC                   5F5E6ACD (1600023245)\n+1703 Compressed Size       00000F00 (3840)\n+1707 Uncompressed Size     00003F85 (16261)\n 170B Filename Length       003D (61)\n 170D Extra Length          0000 (0)\n 170F Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n # WARNING: Offset 0x170F: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n 174C PAYLOAD\n \n-263A LOCAL HEADER #20      04034B50 (67324752)\n-263E Extract Zip Spec      14 (20) '2.0'\n-263F Extract OS            00 (0) 'MS-DOS'\n-2640 General Purpose Flag  0800 (2048)\n+264C LOCAL HEADER #20      04034B50 (67324752)\n+2650 Extract Zip Spec      14 (20) '2.0'\n+2651 Extract OS            00 (0) 'MS-DOS'\n+2652 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-2642 Compression Method    0008 (8) 'Deflated'\n-2644 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-2648 CRC                   03D1B931 (64076081)\n-264C Compressed Size       00000748 (1864)\n-2650 Uncompressed Size     000018E3 (6371)\n-2654 Filename Length       003E (62)\n-2656 Extra Length          0000 (0)\n-2658 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+2654 Compression Method    0008 (8) 'Deflated'\n+2656 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+265A CRC                   980C94D0 (2550961360)\n+265E Compressed Size       00000755 (1877)\n+2662 Uncompressed Size     0000199A (6554)\n+2666 Filename Length       003E (62)\n+2668 Extra Length          0000 (0)\n+266A Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x2658: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x266A: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-2696 PAYLOAD\n+26A8 PAYLOAD\n \n-2DDE LOCAL HEADER #21      04034B50 (67324752)\n-2DE2 Extract Zip Spec      14 (20) '2.0'\n-2DE3 Extract OS            00 (0) 'MS-DOS'\n-2DE4 General Purpose Flag  0800 (2048)\n+2DFD LOCAL HEADER #21      04034B50 (67324752)\n+2E01 Extract Zip Spec      14 (20) '2.0'\n+2E02 Extract OS            00 (0) 'MS-DOS'\n+2E03 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-2DE6 Compression Method    0008 (8) 'Deflated'\n-2DE8 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-2DEC CRC                   F93BB070 (4181438576)\n-2DF0 Compressed Size       000003F3 (1011)\n-2DF4 Uncompressed Size     000008B8 (2232)\n-2DF8 Filename Length       0032 (50)\n-2DFA Extra Length          0000 (0)\n-2DFC Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+2E05 Compression Method    0008 (8) 'Deflated'\n+2E07 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+2E0B CRC                   4C7D08FC (1283262716)\n+2E0F Compressed Size       000003FD (1021)\n+2E13 Uncompressed Size     000008FF (2303)\n+2E17 Filename Length       0032 (50)\n+2E19 Extra Length          0000 (0)\n+2E1B Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x2DFC: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x2E1B: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-2E2E PAYLOAD\n+2E4D PAYLOAD\n \n-3221 LOCAL HEADER #22      04034B50 (67324752)\n-3225 Extract Zip Spec      14 (20) '2.0'\n-3226 Extract OS            00 (0) 'MS-DOS'\n-3227 General Purpose Flag  0800 (2048)\n+324A LOCAL HEADER #22      04034B50 (67324752)\n+324E Extract Zip Spec      14 (20) '2.0'\n+324F Extract OS            00 (0) 'MS-DOS'\n+3250 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-3229 Compression Method    0008 (8) 'Deflated'\n-322B Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-322F CRC                   C7D35A4B (3352517195)\n-3233 Compressed Size       000008E7 (2279)\n-3237 Uncompressed Size     00001F36 (7990)\n-323B Filename Length       0040 (64)\n-323D Extra Length          0000 (0)\n-323F Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+3252 Compression Method    0008 (8) 'Deflated'\n+3254 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+3258 CRC                   EAE8515F (3941093727)\n+325C Compressed Size       000008F1 (2289)\n+3260 Uncompressed Size     00001FF9 (8185)\n+3264 Filename Length       0040 (64)\n+3266 Extra Length          0000 (0)\n+3268 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x323F: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x3268: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-327F PAYLOAD\n+32A8 PAYLOAD\n \n-3B66 LOCAL HEADER #23      04034B50 (67324752)\n-3B6A Extract Zip Spec      14 (20) '2.0'\n-3B6B Extract OS            00 (0) 'MS-DOS'\n-3B6C General Purpose Flag  0800 (2048)\n+3B99 LOCAL HEADER #23      04034B50 (67324752)\n+3B9D Extract Zip Spec      14 (20) '2.0'\n+3B9E Extract OS            00 (0) 'MS-DOS'\n+3B9F General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-3B6E Compression Method    0008 (8) 'Deflated'\n-3B70 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-3B74 CRC                   D012E5FC (3490899452)\n-3B78 Compressed Size       000007FD (2045)\n-3B7C Uncompressed Size     00001BA0 (7072)\n-3B80 Filename Length       003C (60)\n-3B82 Extra Length          0000 (0)\n-3B84 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+3BA1 Compression Method    0008 (8) 'Deflated'\n+3BA3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+3BA7 CRC                   E202F321 (3791844129)\n+3BAB Compressed Size       0000080B (2059)\n+3BAF Uncompressed Size     00001C58 (7256)\n+3BB3 Filename Length       003C (60)\n+3BB5 Extra Length          0000 (0)\n+3BB7 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x3B84: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x3BB7: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-3BC0 PAYLOAD\n+3BF3 PAYLOAD\n \n-43BD LOCAL HEADER #24      04034B50 (67324752)\n-43C1 Extract Zip Spec      14 (20) '2.0'\n-43C2 Extract OS            00 (0) 'MS-DOS'\n-43C3 General Purpose Flag  0800 (2048)\n+43FE LOCAL HEADER #24      04034B50 (67324752)\n+4402 Extract Zip Spec      14 (20) '2.0'\n+4403 Extract OS            00 (0) 'MS-DOS'\n+4404 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-43C5 Compression Method    0008 (8) 'Deflated'\n-43C7 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-43CB CRC                   A6D38CE4 (2798882020)\n-43CF Compressed Size       00000A39 (2617)\n-43D3 Uncompressed Size     00002AE7 (10983)\n-43D7 Filename Length       0033 (51)\n-43D9 Extra Length          0000 (0)\n-43DB Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+4406 Compression Method    0008 (8) 'Deflated'\n+4408 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+440C CRC                   DBBCD787 (3686586247)\n+4410 Compressed Size       00000A4C (2636)\n+4414 Uncompressed Size     00002BDF (11231)\n+4418 Filename Length       0033 (51)\n+441A Extra Length          0000 (0)\n+441C Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x43DB: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x441C: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-440E PAYLOAD\n+444F PAYLOAD\n \n-4E47 LOCAL HEADER #25      04034B50 (67324752)\n-4E4B Extract Zip Spec      14 (20) '2.0'\n-4E4C Extract OS            00 (0) 'MS-DOS'\n-4E4D General Purpose Flag  0800 (2048)\n+4E9B LOCAL HEADER #25      04034B50 (67324752)\n+4E9F Extract Zip Spec      14 (20) '2.0'\n+4EA0 Extract OS            00 (0) 'MS-DOS'\n+4EA1 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-4E4F Compression Method    0008 (8) 'Deflated'\n-4E51 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-4E55 CRC                   982FC700 (2553267968)\n-4E59 Compressed Size       00000370 (880)\n-4E5D Uncompressed Size     00000A19 (2585)\n-4E61 Filename Length       003A (58)\n-4E63 Extra Length          0000 (0)\n-4E65 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+4EA3 Compression Method    0008 (8) 'Deflated'\n+4EA5 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+4EA9 CRC                   E1297FD5 (3777593301)\n+4EAD Compressed Size       0000037A (890)\n+4EB1 Uncompressed Size     00000A4E (2638)\n+4EB5 Filename Length       003A (58)\n+4EB7 Extra Length          0000 (0)\n+4EB9 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x4E65: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x4EB9: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-4E9F PAYLOAD\n+4EF3 PAYLOAD\n \n-520F LOCAL HEADER #26      04034B50 (67324752)\n-5213 Extract Zip Spec      14 (20) '2.0'\n-5214 Extract OS            00 (0) 'MS-DOS'\n-5215 General Purpose Flag  0800 (2048)\n+526D LOCAL HEADER #26      04034B50 (67324752)\n+5271 Extract Zip Spec      14 (20) '2.0'\n+5272 Extract OS            00 (0) 'MS-DOS'\n+5273 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-5217 Compression Method    0008 (8) 'Deflated'\n-5219 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-521D CRC                   C6A73CC6 (3332848838)\n-5221 Compressed Size       0000045E (1118)\n-5225 Uncompressed Size     00000C1E (3102)\n-5229 Filename Length       0038 (56)\n-522B Extra Length          0000 (0)\n-522D Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+5275 Compression Method    0008 (8) 'Deflated'\n+5277 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+527B CRC                   CDBF443E (3451864126)\n+527F Compressed Size       00000466 (1126)\n+5283 Uncompressed Size     00000C74 (3188)\n+5287 Filename Length       0038 (56)\n+5289 Extra Length          0000 (0)\n+528B Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x522D: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x528B: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-5265 PAYLOAD\n+52C3 PAYLOAD\n \n-56C3 LOCAL HEADER #27      04034B50 (67324752)\n-56C7 Extract Zip Spec      14 (20) '2.0'\n-56C8 Extract OS            00 (0) 'MS-DOS'\n-56C9 General Purpose Flag  0800 (2048)\n+5729 LOCAL HEADER #27      04034B50 (67324752)\n+572D Extract Zip Spec      14 (20) '2.0'\n+572E Extract OS            00 (0) 'MS-DOS'\n+572F General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-56CB Compression Method    0008 (8) 'Deflated'\n-56CD Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-56D1 CRC                   94899E78 (2492046968)\n-56D5 Compressed Size       000002B3 (691)\n-56D9 Uncompressed Size     000005B1 (1457)\n-56DD Filename Length       0036 (54)\n-56DF Extra Length          0000 (0)\n-56E1 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+5731 Compression Method    0008 (8) 'Deflated'\n+5733 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+5737 CRC                   151E182C (354293804)\n+573B Compressed Size       000002BC (700)\n+573F Uncompressed Size     000005DD (1501)\n+5743 Filename Length       0036 (54)\n+5745 Extra Length          0000 (0)\n+5747 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x56E1: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x5747: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-5717 PAYLOAD\n+577D PAYLOAD\n \n-59CA LOCAL HEADER #28      04034B50 (67324752)\n-59CE Extract Zip Spec      14 (20) '2.0'\n-59CF Extract OS            00 (0) 'MS-DOS'\n-59D0 General Purpose Flag  0800 (2048)\n+5A39 LOCAL HEADER #28      04034B50 (67324752)\n+5A3D Extract Zip Spec      14 (20) '2.0'\n+5A3E Extract OS            00 (0) 'MS-DOS'\n+5A3F General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-59D2 Compression Method    0008 (8) 'Deflated'\n-59D4 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-59D8 CRC                   4247D839 (1112004665)\n-59DC Compressed Size       00000956 (2390)\n-59E0 Uncompressed Size     00001FD9 (8153)\n-59E4 Filename Length       0035 (53)\n-59E6 Extra Length          0000 (0)\n-59E8 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+5A41 Compression Method    0008 (8) 'Deflated'\n+5A43 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+5A47 CRC                   39CBA339 (969646905)\n+5A4B Compressed Size       00000962 (2402)\n+5A4F Uncompressed Size     00002090 (8336)\n+5A53 Filename Length       0035 (53)\n+5A55 Extra Length          0000 (0)\n+5A57 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x59E8: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x5A57: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-5A1D PAYLOAD\n+5A8C PAYLOAD\n \n-6373 LOCAL HEADER #29      04034B50 (67324752)\n-6377 Extract Zip Spec      14 (20) '2.0'\n-6378 Extract OS            00 (0) 'MS-DOS'\n-6379 General Purpose Flag  0800 (2048)\n+63EE LOCAL HEADER #29      04034B50 (67324752)\n+63F2 Extract Zip Spec      14 (20) '2.0'\n+63F3 Extract OS            00 (0) 'MS-DOS'\n+63F4 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-637B Compression Method    0008 (8) 'Deflated'\n-637D Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-6381 CRC                   C2B511E4 (3266646500)\n-6385 Compressed Size       00001872 (6258)\n-6389 Uncompressed Size     00006B37 (27447)\n-638D Filename Length       0036 (54)\n-638F Extra Length          0000 (0)\n-6391 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+63F6 Compression Method    0008 (8) 'Deflated'\n+63F8 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+63FC CRC                   07C16F02 (130117378)\n+6400 Compressed Size       00001890 (6288)\n+6404 Uncompressed Size     00006DE5 (28133)\n+6408 Filename Length       0036 (54)\n+640A Extra Length          0000 (0)\n+640C Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x6391: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x640C: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-63C7 PAYLOAD\n+6442 PAYLOAD\n \n-7C39 LOCAL HEADER #30      04034B50 (67324752)\n-7C3D Extract Zip Spec      14 (20) '2.0'\n-7C3E Extract OS            00 (0) 'MS-DOS'\n-7C3F General Purpose Flag  0800 (2048)\n+7CD2 LOCAL HEADER #30      04034B50 (67324752)\n+7CD6 Extract Zip Spec      14 (20) '2.0'\n+7CD7 Extract OS            00 (0) 'MS-DOS'\n+7CD8 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-7C41 Compression Method    0008 (8) 'Deflated'\n-7C43 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7C47 CRC                   7317DB5C (1930943324)\n-7C4B Compressed Size       000002DB (731)\n-7C4F Uncompressed Size     00000714 (1812)\n-7C53 Filename Length       003C (60)\n-7C55 Extra Length          0000 (0)\n-7C57 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+7CDA Compression Method    0008 (8) 'Deflated'\n+7CDC Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+7CE0 CRC                   DA119291 (3658584721)\n+7CE4 Compressed Size       000002E4 (740)\n+7CE8 Uncompressed Size     00000752 (1874)\n+7CEC Filename Length       003C (60)\n+7CEE Extra Length          0000 (0)\n+7CF0 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7C57: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x7CF0: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-7C93 PAYLOAD\n+7D2C PAYLOAD\n \n-7F6E LOCAL HEADER #31      04034B50 (67324752)\n-7F72 Extract Zip Spec      14 (20) '2.0'\n-7F73 Extract OS            00 (0) 'MS-DOS'\n-7F74 General Purpose Flag  0800 (2048)\n+8010 LOCAL HEADER #31      04034B50 (67324752)\n+8014 Extract Zip Spec      14 (20) '2.0'\n+8015 Extract OS            00 (0) 'MS-DOS'\n+8016 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-7F76 Compression Method    0008 (8) 'Deflated'\n-7F78 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-7F7C CRC                   344C1E36 (877403702)\n-7F80 Compressed Size       00000817 (2071)\n-7F84 Uncompressed Size     00001FCC (8140)\n-7F88 Filename Length       0042 (66)\n-7F8A Extra Length          0000 (0)\n-7F8C Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+8018 Compression Method    0008 (8) 'Deflated'\n+801A Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+801E CRC                   0574FE58 (91553368)\n+8022 Compressed Size       0000082B (2091)\n+8026 Uncompressed Size     000020D9 (8409)\n+802A Filename Length       0042 (66)\n+802C Extra Length          0000 (0)\n+802E Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x7F8C: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x802E: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-7FCE PAYLOAD\n+8070 PAYLOAD\n \n-87E5 LOCAL HEADER #32      04034B50 (67324752)\n-87E9 Extract Zip Spec      14 (20) '2.0'\n-87EA Extract OS            00 (0) 'MS-DOS'\n-87EB General Purpose Flag  0800 (2048)\n+889B LOCAL HEADER #32      04034B50 (67324752)\n+889F Extract Zip Spec      14 (20) '2.0'\n+88A0 Extract OS            00 (0) 'MS-DOS'\n+88A1 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-87ED Compression Method    0008 (8) 'Deflated'\n-87EF Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-87F3 CRC                   3B14B127 (991211815)\n-87F7 Compressed Size       000006AF (1711)\n-87FB Uncompressed Size     000017C7 (6087)\n-87FF Filename Length       0045 (69)\n-8801 Extra Length          0000 (0)\n-8803 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+88A3 Compression Method    0008 (8) 'Deflated'\n+88A5 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+88A9 CRC                   B5644E62 (3043249762)\n+88AD Compressed Size       000006BD (1725)\n+88B1 Uncompressed Size     0000189A (6298)\n+88B5 Filename Length       0045 (69)\n+88B7 Extra Length          0000 (0)\n+88B9 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x8803: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x88B9: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-8848 PAYLOAD\n+88FE PAYLOAD\n \n-8EF7 LOCAL HEADER #33      04034B50 (67324752)\n-8EFB Extract Zip Spec      14 (20) '2.0'\n-8EFC Extract OS            00 (0) 'MS-DOS'\n-8EFD General Purpose Flag  0800 (2048)\n+8FBB LOCAL HEADER #33      04034B50 (67324752)\n+8FBF Extract Zip Spec      14 (20) '2.0'\n+8FC0 Extract OS            00 (0) 'MS-DOS'\n+8FC1 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-8EFF Compression Method    0008 (8) 'Deflated'\n-8F01 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-8F05 CRC                   1915FFAE (420872110)\n-8F09 Compressed Size       000007CC (1996)\n-8F0D Uncompressed Size     00002228 (8744)\n-8F11 Filename Length       003C (60)\n-8F13 Extra Length          0000 (0)\n-8F15 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+8FC3 Compression Method    0008 (8) 'Deflated'\n+8FC5 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+8FC9 CRC                   45086F19 (1158180633)\n+8FCD Compressed Size       000007DA (2010)\n+8FD1 Uncompressed Size     000022F3 (8947)\n+8FD5 Filename Length       003C (60)\n+8FD7 Extra Length          0000 (0)\n+8FD9 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x8F15: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x8FD9: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-8F51 PAYLOAD\n+9015 PAYLOAD\n \n-971D LOCAL HEADER #34      04034B50 (67324752)\n-9721 Extract Zip Spec      14 (20) '2.0'\n-9722 Extract OS            00 (0) 'MS-DOS'\n-9723 General Purpose Flag  0800 (2048)\n+97EF LOCAL HEADER #34      04034B50 (67324752)\n+97F3 Extract Zip Spec      14 (20) '2.0'\n+97F4 Extract OS            00 (0) 'MS-DOS'\n+97F5 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-9725 Compression Method    0008 (8) 'Deflated'\n-9727 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-972B CRC                   B4BC5053 (3032240211)\n-972F Compressed Size       00000685 (1669)\n-9733 Uncompressed Size     00001648 (5704)\n-9737 Filename Length       003B (59)\n-9739 Extra Length          0000 (0)\n-973B Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+97F7 Compression Method    0008 (8) 'Deflated'\n+97F9 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+97FD CRC                   57E4B8CF (1474607311)\n+9801 Compressed Size       0000068F (1679)\n+9805 Uncompressed Size     000016C7 (5831)\n+9809 Filename Length       003B (59)\n+980B Extra Length          0000 (0)\n+980D Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x973B: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x980D: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-9776 PAYLOAD\n+9848 PAYLOAD\n \n-9DFB LOCAL HEADER #35      04034B50 (67324752)\n-9DFF Extract Zip Spec      14 (20) '2.0'\n-9E00 Extract OS            00 (0) 'MS-DOS'\n-9E01 General Purpose Flag  0800 (2048)\n+9ED7 LOCAL HEADER #35      04034B50 (67324752)\n+9EDB Extract Zip Spec      14 (20) '2.0'\n+9EDC Extract OS            00 (0) 'MS-DOS'\n+9EDD General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-9E03 Compression Method    0008 (8) 'Deflated'\n-9E05 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-9E09 CRC                   C9453D78 (3376758136)\n-9E0D Compressed Size       0000038D (909)\n-9E11 Uncompressed Size     000008E4 (2276)\n-9E15 Filename Length       0043 (67)\n-9E17 Extra Length          0000 (0)\n-9E19 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+9EDF Compression Method    0008 (8) 'Deflated'\n+9EE1 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+9EE5 CRC                   A77D588D (2810009741)\n+9EE9 Compressed Size       00000398 (920)\n+9EED Uncompressed Size     00000921 (2337)\n+9EF1 Filename Length       0043 (67)\n+9EF3 Extra Length          0000 (0)\n+9EF5 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0x9E19: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0x9EF5: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-9E5C PAYLOAD\n+9F38 PAYLOAD\n \n-A1E9 LOCAL HEADER #36      04034B50 (67324752)\n-A1ED Extract Zip Spec      14 (20) '2.0'\n-A1EE Extract OS            00 (0) 'MS-DOS'\n-A1EF General Purpose Flag  0800 (2048)\n+A2D0 LOCAL HEADER #36      04034B50 (67324752)\n+A2D4 Extract Zip Spec      14 (20) '2.0'\n+A2D5 Extract OS            00 (0) 'MS-DOS'\n+A2D6 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-A1F1 Compression Method    0008 (8) 'Deflated'\n-A1F3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-A1F7 CRC                   5A226E99 (1512205977)\n-A1FB Compressed Size       00000465 (1125)\n-A1FF Uncompressed Size     00000B86 (2950)\n-A203 Filename Length       0047 (71)\n-A205 Extra Length          0000 (0)\n-A207 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+A2D8 Compression Method    0008 (8) 'Deflated'\n+A2DA Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+A2DE CRC                   DF443A2F (3745790511)\n+A2E2 Compressed Size       00000471 (1137)\n+A2E6 Uncompressed Size     00000BC9 (3017)\n+A2EA Filename Length       0047 (71)\n+A2EC Extra Length          0000 (0)\n+A2EE Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xA207: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xA2EE: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-A24E PAYLOAD\n+A335 PAYLOAD\n \n-A6B3 LOCAL HEADER #37      04034B50 (67324752)\n-A6B7 Extract Zip Spec      14 (20) '2.0'\n-A6B8 Extract OS            00 (0) 'MS-DOS'\n-A6B9 General Purpose Flag  0800 (2048)\n+A7A6 LOCAL HEADER #37      04034B50 (67324752)\n+A7AA Extract Zip Spec      14 (20) '2.0'\n+A7AB Extract OS            00 (0) 'MS-DOS'\n+A7AC General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-A6BB Compression Method    0008 (8) 'Deflated'\n-A6BD Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-A6C1 CRC                   2D68A65E (761833054)\n-A6C5 Compressed Size       00000052 (82)\n-A6C9 Uncompressed Size     00000094 (148)\n-A6CD Filename Length       0044 (68)\n-A6CF Extra Length          0000 (0)\n-A6D1 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+A7AE Compression Method    0008 (8) 'Deflated'\n+A7B0 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+A7B4 CRC                   2D68A65E (761833054)\n+A7B8 Compressed Size       00000052 (82)\n+A7BC Uncompressed Size     00000094 (148)\n+A7C0 Filename Length       0044 (68)\n+A7C2 Extra Length          0000 (0)\n+A7C4 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xA6D1: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xA7C4: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-A715 PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n+A808 PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n \n-A767 LOCAL HEADER #38      04034B50 (67324752)\n-A76B Extract Zip Spec      14 (20) '2.0'\n-A76C Extract OS            00 (0) 'MS-DOS'\n-A76D General Purpose Flag  0800 (2048)\n+A85A LOCAL HEADER #38      04034B50 (67324752)\n+A85E Extract Zip Spec      14 (20) '2.0'\n+A85F Extract OS            00 (0) 'MS-DOS'\n+A860 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-A76F Compression Method    0008 (8) 'Deflated'\n-A771 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-A775 CRC                   A5009E2B (2768281131)\n-A779 Compressed Size       00000031 (49)\n-A77D Uncompressed Size     00000039 (57)\n-A781 Filename Length       0038 (56)\n-A783 Extra Length          0000 (0)\n-A785 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+A862 Compression Method    0008 (8) 'Deflated'\n+A864 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+A868 CRC                   A5009E2B (2768281131)\n+A86C Compressed Size       00000031 (49)\n+A870 Uncompressed Size     00000039 (57)\n+A874 Filename Length       0038 (56)\n+A876 Extra Length          0000 (0)\n+A878 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xA785: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xA878: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-A7BD PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n+A8B0 PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n \n-A7EE LOCAL HEADER #39      04034B50 (67324752)\n-A7F2 Extract Zip Spec      14 (20) '2.0'\n-A7F3 Extract OS            00 (0) 'MS-DOS'\n-A7F4 General Purpose Flag  0800 (2048)\n+A8E1 LOCAL HEADER #39      04034B50 (67324752)\n+A8E5 Extract Zip Spec      14 (20) '2.0'\n+A8E6 Extract OS            00 (0) 'MS-DOS'\n+A8E7 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-A7F6 Compression Method    0008 (8) 'Deflated'\n-A7F8 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-A7FC CRC                   A3C6F966 (2747726182)\n-A800 Compressed Size       00000042 (66)\n-A804 Uncompressed Size     0000007C (124)\n-A808 Filename Length       0033 (51)\n-A80A Extra Length          0000 (0)\n-A80C Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+A8E9 Compression Method    0008 (8) 'Deflated'\n+A8EB Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+A8EF CRC                   A3C6F966 (2747726182)\n+A8F3 Compressed Size       00000042 (66)\n+A8F7 Uncompressed Size     0000007C (124)\n+A8FB Filename Length       0033 (51)\n+A8FD Extra Length          0000 (0)\n+A8FF Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xA80C: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xA8FF: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-A83F PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n+A932 PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n \n-A881 LOCAL HEADER #40      04034B50 (67324752)\n-A885 Extract Zip Spec      14 (20) '2.0'\n-A886 Extract OS            00 (0) 'MS-DOS'\n-A887 General Purpose Flag  0800 (2048)\n+A974 LOCAL HEADER #40      04034B50 (67324752)\n+A978 Extract Zip Spec      14 (20) '2.0'\n+A979 Extract OS            00 (0) 'MS-DOS'\n+A97A General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-A889 Compression Method    0008 (8) 'Deflated'\n-A88B Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-A88F CRC                   83A37AD0 (2208529104)\n-A893 Compressed Size       0000002A (42)\n-A897 Uncompressed Size     00000037 (55)\n-A89B Filename Length       0035 (53)\n-A89D Extra Length          0000 (0)\n-A89F Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+A97C Compression Method    0008 (8) 'Deflated'\n+A97E Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+A982 CRC                   83A37AD0 (2208529104)\n+A986 Compressed Size       0000002A (42)\n+A98A Uncompressed Size     00000037 (55)\n+A98E Filename Length       0035 (53)\n+A990 Extra Length          0000 (0)\n+A992 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xA89F: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xA992: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-A8D4 PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n+A9C7 PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n \n-A8FE LOCAL HEADER #41      04034B50 (67324752)\n-A902 Extract Zip Spec      14 (20) '2.0'\n-A903 Extract OS            00 (0) 'MS-DOS'\n-A904 General Purpose Flag  0800 (2048)\n+A9F1 LOCAL HEADER #41      04034B50 (67324752)\n+A9F5 Extract Zip Spec      14 (20) '2.0'\n+A9F6 Extract OS            00 (0) 'MS-DOS'\n+A9F7 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-A906 Compression Method    0008 (8) 'Deflated'\n-A908 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-A90C CRC                   45DB5347 (1172001607)\n-A910 Compressed Size       00000448 (1096)\n-A914 Uncompressed Size     00000FBC (4028)\n-A918 Filename Length       0037 (55)\n-A91A Extra Length          0000 (0)\n-A91C Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+A9F9 Compression Method    0008 (8) 'Deflated'\n+A9FB Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+A9FF CRC                   C3B87E97 (3283648151)\n+AA03 Compressed Size       00000441 (1089)\n+AA07 Uncompressed Size     00000F4C (3916)\n+AA0B Filename Length       0037 (55)\n+AA0D Extra Length          0000 (0)\n+AA0F Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xA91C: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xAA0F: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-A953 PAYLOAD\n+AA46 PAYLOAD\n \n-AD9B LOCAL HEADER #42      04034B50 (67324752)\n-AD9F Extract Zip Spec      14 (20) '2.0'\n-ADA0 Extract OS            00 (0) 'MS-DOS'\n-ADA1 General Purpose Flag  0800 (2048)\n+AE87 LOCAL HEADER #42      04034B50 (67324752)\n+AE8B Extract Zip Spec      14 (20) '2.0'\n+AE8C Extract OS            00 (0) 'MS-DOS'\n+AE8D General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-ADA3 Compression Method    0008 (8) 'Deflated'\n-ADA5 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-ADA9 CRC                   BE4436A8 (3192141480)\n-ADAD Compressed Size       0000003E (62)\n-ADB1 Uncompressed Size     00000046 (70)\n-ADB5 Filename Length       003E (62)\n-ADB7 Extra Length          0000 (0)\n-ADB9 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+AE8F Compression Method    0008 (8) 'Deflated'\n+AE91 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+AE95 CRC                   BE4436A8 (3192141480)\n+AE99 Compressed Size       0000003E (62)\n+AE9D Uncompressed Size     00000046 (70)\n+AEA1 Filename Length       003E (62)\n+AEA3 Extra Length          0000 (0)\n+AEA5 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xADB9: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xAEA5: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-ADF7 PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n+AEE3 PAYLOAD               XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n \n-AE35 CENTRAL HEADER #1     02014B50 (33639248)\n-AE39 Created Zip Spec      14 (20) '2.0'\n-AE3A Created OS            03 (3) 'Unix'\n-AE3B Extract Zip Spec      14 (20) '2.0'\n-AE3C Extract OS            00 (0) 'MS-DOS'\n-AE3D General Purpose Flag  0800 (2048)\n+AF21 CENTRAL HEADER #1     02014B50 (33639248)\n+AF25 Created Zip Spec      14 (20) '2.0'\n+AF26 Created OS            03 (3) 'Unix'\n+AF27 Extract Zip Spec      14 (20) '2.0'\n+AF28 Extract OS            00 (0) 'MS-DOS'\n+AF29 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-AE3F Compression Method    0008 (8) 'Deflated'\n-AE41 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-AE45 CRC                   A689EB18 (2794056472)\n-AE49 Compressed Size       00000042 (66)\n-AE4D Uncompressed Size     00000040 (64)\n-AE51 Filename Length       0014 (20)\n-AE53 Extra Length          0000 (0)\n-AE55 Comment Length        0000 (0)\n-AE57 Disk Start            0000 (0)\n-AE59 Int File Attributes   0000 (0)\n+AF2B Compression Method    0008 (8) 'Deflated'\n+AF2D Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+AF31 CRC                   A689EB18 (2794056472)\n+AF35 Compressed Size       00000042 (66)\n+AF39 Uncompressed Size     00000040 (64)\n+AF3D Filename Length       0014 (20)\n+AF3F Extra Length          0000 (0)\n+AF41 Comment Length        0000 (0)\n+AF43 Disk Start            0000 (0)\n+AF45 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-AE5B Ext File Attributes   81A40000 (2175008768)\n+AF47 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-AE5F Local Header Offset   00000000 (0)\n-AE63 Filename              'XXXXXXXXXXXXXXXXXXXX'\n+AF4B Local Header Offset   00000000 (0)\n+AF4F Filename              'XXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xAE63: Filename 'XXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xAF4F: Filename 'XXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-AE77 CENTRAL HEADER #2     02014B50 (33639248)\n-AE7B Created Zip Spec      14 (20) '2.0'\n-AE7C Created OS            03 (3) 'Unix'\n-AE7D Extract Zip Spec      0A (10) '1.0'\n-AE7E Extract OS            00 (0) 'MS-DOS'\n-AE7F General Purpose Flag  0800 (2048)\n+AF63 CENTRAL HEADER #2     02014B50 (33639248)\n+AF67 Created Zip Spec      14 (20) '2.0'\n+AF68 Created OS            03 (3) 'Unix'\n+AF69 Extract Zip Spec      0A (10) '1.0'\n+AF6A Extract OS            00 (0) 'MS-DOS'\n+AF6B General Purpose Flag  0800 (2048)\n      [Bit 11]              1 'Language Encoding'\n-AE81 Compression Method    0000 (0) 'Stored'\n-AE83 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-AE87 CRC                   00000000 (0)\n-AE8B Compressed Size       00000000 (0)\n-AE8F Uncompressed Size     00000000 (0)\n-AE93 Filename Length       0009 (9)\n-AE95 Extra Length          0000 (0)\n-AE97 Comment Length        0000 (0)\n-AE99 Disk Start            0000 (0)\n-AE9B Int File Attributes   0000 (0)\n+AF6D Compression Method    0000 (0) 'Stored'\n+AF6F Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+AF73 CRC                   00000000 (0)\n+AF77 Compressed Size       00000000 (0)\n+AF7B Uncompressed Size     00000000 (0)\n+AF7F Filename Length       0009 (9)\n+AF81 Extra Length          0000 (0)\n+AF83 Comment Length        0000 (0)\n+AF85 Disk Start            0000 (0)\n+AF87 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-AE9D Ext File Attributes   41ED0010 (1106051088)\n+AF89 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-AEA1 Local Header Offset   00000074 (116)\n-AEA5 Filename              'XXXXXXXXX'\n+AF8D Local Header Offset   00000074 (116)\n+AF91 Filename              'XXXXXXXXX'\n #\n-# WARNING: Offset 0xAEA5: Filename 'XXXXXXXXX'\n+# WARNING: Offset 0xAF91: Filename 'XXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xAEA5: Directory 'XXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xAF91: Directory 'XXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xAE7D: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXX'\n+# WARNING: Offset 0xAF69: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXX'\n #\n \n-AEAE CENTRAL HEADER #3     02014B50 (33639248)\n-AEB2 Created Zip Spec      14 (20) '2.0'\n-AEB3 Created OS            03 (3) 'Unix'\n-AEB4 Extract Zip Spec      0A (10) '1.0'\n-AEB5 Extract OS            00 (0) 'MS-DOS'\n-AEB6 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-AEB8 Compression Method    0000 (0) 'Stored'\n-AEBA Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-AEBE CRC                   00000000 (0)\n-AEC2 Compressed Size       00000000 (0)\n-AEC6 Uncompressed Size     00000000 (0)\n-AECA Filename Length       0004 (4)\n-AECC Extra Length          0000 (0)\n-AECE Comment Length        0000 (0)\n-AED0 Disk Start            0000 (0)\n-AED2 Int File Attributes   0000 (0)\n+AF9A CENTRAL HEADER #3     02014B50 (33639248)\n+AF9E Created Zip Spec      14 (20) '2.0'\n+AF9F Created OS            03 (3) 'Unix'\n+AFA0 Extract Zip Spec      0A (10) '1.0'\n+AFA1 Extract OS            00 (0) 'MS-DOS'\n+AFA2 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+AFA4 Compression Method    0000 (0) 'Stored'\n+AFA6 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+AFAA CRC                   00000000 (0)\n+AFAE Compressed Size       00000000 (0)\n+AFB2 Uncompressed Size     00000000 (0)\n+AFB6 Filename Length       0004 (4)\n+AFB8 Extra Length          0000 (0)\n+AFBA Comment Length        0000 (0)\n+AFBC Disk Start            0000 (0)\n+AFBE Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-AED4 Ext File Attributes   41ED0010 (1106051088)\n+AFC0 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-AED8 Local Header Offset   0000009B (155)\n-AEDC Filename              'XXXX'\n+AFC4 Local Header Offset   0000009B (155)\n+AFC8 Filename              'XXXX'\n #\n-# WARNING: Offset 0xAEDC: Filename 'XXXX'\n+# WARNING: Offset 0xAFC8: Filename 'XXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xAEDC: Directory 'XXXX' must end in a '/'\n+# ERROR: Offset 0xAFC8: Directory 'XXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xAEB4: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXX'\n+# WARNING: Offset 0xAFA0: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXX'\n #\n \n-AEE0 CENTRAL HEADER #4     02014B50 (33639248)\n-AEE4 Created Zip Spec      14 (20) '2.0'\n-AEE5 Created OS            03 (3) 'Unix'\n-AEE6 Extract Zip Spec      0A (10) '1.0'\n-AEE7 Extract OS            00 (0) 'MS-DOS'\n-AEE8 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-AEEA Compression Method    0000 (0) 'Stored'\n-AEEC Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-AEF0 CRC                   00000000 (0)\n-AEF4 Compressed Size       00000000 (0)\n-AEF8 Uncompressed Size     00000000 (0)\n-AEFC Filename Length       000B (11)\n-AEFE Extra Length          0000 (0)\n-AF00 Comment Length        0000 (0)\n-AF02 Disk Start            0000 (0)\n-AF04 Int File Attributes   0000 (0)\n+AFCC CENTRAL HEADER #4     02014B50 (33639248)\n+AFD0 Created Zip Spec      14 (20) '2.0'\n+AFD1 Created OS            03 (3) 'Unix'\n+AFD2 Extract Zip Spec      0A (10) '1.0'\n+AFD3 Extract OS            00 (0) 'MS-DOS'\n+AFD4 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+AFD6 Compression Method    0000 (0) 'Stored'\n+AFD8 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+AFDC CRC                   00000000 (0)\n+AFE0 Compressed Size       00000000 (0)\n+AFE4 Uncompressed Size     00000000 (0)\n+AFE8 Filename Length       000B (11)\n+AFEA Extra Length          0000 (0)\n+AFEC Comment Length        0000 (0)\n+AFEE Disk Start            0000 (0)\n+AFF0 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-AF06 Ext File Attributes   41ED0010 (1106051088)\n+AFF2 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-AF0A Local Header Offset   000000BD (189)\n-AF0E Filename              'XXXXXXXXXXX'\n+AFF6 Local Header Offset   000000BD (189)\n+AFFA Filename              'XXXXXXXXXXX'\n #\n-# WARNING: Offset 0xAF0E: Filename 'XXXXXXXXXXX'\n+# WARNING: Offset 0xAFFA: Filename 'XXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xAF0E: Directory 'XXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xAFFA: Directory 'XXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xAEE6: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXX'\n+# WARNING: Offset 0xAFD2: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXX'\n #\n \n-AF19 CENTRAL HEADER #5     02014B50 (33639248)\n-AF1D Created Zip Spec      14 (20) '2.0'\n-AF1E Created OS            03 (3) 'Unix'\n-AF1F Extract Zip Spec      0A (10) '1.0'\n-AF20 Extract OS            00 (0) 'MS-DOS'\n-AF21 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-AF23 Compression Method    0000 (0) 'Stored'\n-AF25 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-AF29 CRC                   00000000 (0)\n-AF2D Compressed Size       00000000 (0)\n-AF31 Uncompressed Size     00000000 (0)\n-AF35 Filename Length       0011 (17)\n-AF37 Extra Length          0000 (0)\n-AF39 Comment Length        0000 (0)\n-AF3B Disk Start            0000 (0)\n-AF3D Int File Attributes   0000 (0)\n+B005 CENTRAL HEADER #5     02014B50 (33639248)\n+B009 Created Zip Spec      14 (20) '2.0'\n+B00A Created OS            03 (3) 'Unix'\n+B00B Extract Zip Spec      0A (10) '1.0'\n+B00C Extract OS            00 (0) 'MS-DOS'\n+B00D General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+B00F Compression Method    0000 (0) 'Stored'\n+B011 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B015 CRC                   00000000 (0)\n+B019 Compressed Size       00000000 (0)\n+B01D Uncompressed Size     00000000 (0)\n+B021 Filename Length       0011 (17)\n+B023 Extra Length          0000 (0)\n+B025 Comment Length        0000 (0)\n+B027 Disk Start            0000 (0)\n+B029 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-AF3F Ext File Attributes   41ED0010 (1106051088)\n+B02B Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-AF43 Local Header Offset   000000E6 (230)\n-AF47 Filename              'XXXXXXXXXXXXXXXXX'\n+B02F Local Header Offset   000000E6 (230)\n+B033 Filename              'XXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xAF47: Filename 'XXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB033: Filename 'XXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xAF47: Directory 'XXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xB033: Directory 'XXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xAF1F: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB00B: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXX'\n #\n \n-AF58 CENTRAL HEADER #6     02014B50 (33639248)\n-AF5C Created Zip Spec      14 (20) '2.0'\n-AF5D Created OS            03 (3) 'Unix'\n-AF5E Extract Zip Spec      0A (10) '1.0'\n-AF5F Extract OS            00 (0) 'MS-DOS'\n-AF60 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-AF62 Compression Method    0000 (0) 'Stored'\n-AF64 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-AF68 CRC                   00000000 (0)\n-AF6C Compressed Size       00000000 (0)\n-AF70 Uncompressed Size     00000000 (0)\n-AF74 Filename Length       0015 (21)\n-AF76 Extra Length          0000 (0)\n-AF78 Comment Length        0000 (0)\n-AF7A Disk Start            0000 (0)\n-AF7C Int File Attributes   0000 (0)\n+B044 CENTRAL HEADER #6     02014B50 (33639248)\n+B048 Created Zip Spec      14 (20) '2.0'\n+B049 Created OS            03 (3) 'Unix'\n+B04A Extract Zip Spec      0A (10) '1.0'\n+B04B Extract OS            00 (0) 'MS-DOS'\n+B04C General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+B04E Compression Method    0000 (0) 'Stored'\n+B050 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B054 CRC                   00000000 (0)\n+B058 Compressed Size       00000000 (0)\n+B05C Uncompressed Size     00000000 (0)\n+B060 Filename Length       0015 (21)\n+B062 Extra Length          0000 (0)\n+B064 Comment Length        0000 (0)\n+B066 Disk Start            0000 (0)\n+B068 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-AF7E Ext File Attributes   41ED0010 (1106051088)\n+B06A Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-AF82 Local Header Offset   00000115 (277)\n-AF86 Filename              'XXXXXXXXXXXXXXXXXXXXX'\n+B06E Local Header Offset   00000115 (277)\n+B072 Filename              'XXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xAF86: Filename 'XXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB072: Filename 'XXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xAF86: Directory 'XXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xB072: Directory 'XXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xAF5E: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB04A: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXX'\n #\n \n-AF9B CENTRAL HEADER #7     02014B50 (33639248)\n-AF9F Created Zip Spec      14 (20) '2.0'\n-AFA0 Created OS            03 (3) 'Unix'\n-AFA1 Extract Zip Spec      0A (10) '1.0'\n-AFA2 Extract OS            00 (0) 'MS-DOS'\n-AFA3 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-AFA5 Compression Method    0000 (0) 'Stored'\n-AFA7 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-AFAB CRC                   00000000 (0)\n-AFAF Compressed Size       00000000 (0)\n-AFB3 Uncompressed Size     00000000 (0)\n-AFB7 Filename Length       001E (30)\n-AFB9 Extra Length          0000 (0)\n-AFBB Comment Length        0000 (0)\n-AFBD Disk Start            0000 (0)\n-AFBF Int File Attributes   0000 (0)\n+B087 CENTRAL HEADER #7     02014B50 (33639248)\n+B08B Created Zip Spec      14 (20) '2.0'\n+B08C Created OS            03 (3) 'Unix'\n+B08D Extract Zip Spec      0A (10) '1.0'\n+B08E Extract OS            00 (0) 'MS-DOS'\n+B08F General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+B091 Compression Method    0000 (0) 'Stored'\n+B093 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B097 CRC                   00000000 (0)\n+B09B Compressed Size       00000000 (0)\n+B09F Uncompressed Size     00000000 (0)\n+B0A3 Filename Length       001E (30)\n+B0A5 Extra Length          0000 (0)\n+B0A7 Comment Length        0000 (0)\n+B0A9 Disk Start            0000 (0)\n+B0AB Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-AFC1 Ext File Attributes   41ED0010 (1106051088)\n+B0AD Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-AFC5 Local Header Offset   00000148 (328)\n-AFC9 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B0B1 Local Header Offset   00000148 (328)\n+B0B5 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xAFC9: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB0B5: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xAFC9: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xB0B5: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xAFA1: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB08D: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-AFE7 CENTRAL HEADER #8     02014B50 (33639248)\n-AFEB Created Zip Spec      14 (20) '2.0'\n-AFEC Created OS            03 (3) 'Unix'\n-AFED Extract Zip Spec      0A (10) '1.0'\n-AFEE Extract OS            00 (0) 'MS-DOS'\n-AFEF General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-AFF1 Compression Method    0000 (0) 'Stored'\n-AFF3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-AFF7 CRC                   00000000 (0)\n-AFFB Compressed Size       00000000 (0)\n-AFFF Uncompressed Size     00000000 (0)\n-B003 Filename Length       0024 (36)\n-B005 Extra Length          0000 (0)\n-B007 Comment Length        0000 (0)\n-B009 Disk Start            0000 (0)\n-B00B Int File Attributes   0000 (0)\n+B0D3 CENTRAL HEADER #8     02014B50 (33639248)\n+B0D7 Created Zip Spec      14 (20) '2.0'\n+B0D8 Created OS            03 (3) 'Unix'\n+B0D9 Extract Zip Spec      0A (10) '1.0'\n+B0DA Extract OS            00 (0) 'MS-DOS'\n+B0DB General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+B0DD Compression Method    0000 (0) 'Stored'\n+B0DF Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B0E3 CRC                   00000000 (0)\n+B0E7 Compressed Size       00000000 (0)\n+B0EB Uncompressed Size     00000000 (0)\n+B0EF Filename Length       0024 (36)\n+B0F1 Extra Length          0000 (0)\n+B0F3 Comment Length        0000 (0)\n+B0F5 Disk Start            0000 (0)\n+B0F7 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B00D Ext File Attributes   41ED0010 (1106051088)\n+B0F9 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-B011 Local Header Offset   00000184 (388)\n-B015 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B0FD Local Header Offset   00000184 (388)\n+B101 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB015: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB101: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xB015: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xB101: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xAFED: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB0D9: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-B039 CENTRAL HEADER #9     02014B50 (33639248)\n-B03D Created Zip Spec      14 (20) '2.0'\n-B03E Created OS            03 (3) 'Unix'\n-B03F Extract Zip Spec      0A (10) '1.0'\n-B040 Extract OS            00 (0) 'MS-DOS'\n-B041 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-B043 Compression Method    0000 (0) 'Stored'\n-B045 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B049 CRC                   00000000 (0)\n-B04D Compressed Size       00000000 (0)\n-B051 Uncompressed Size     00000000 (0)\n-B055 Filename Length       002B (43)\n-B057 Extra Length          0000 (0)\n-B059 Comment Length        0000 (0)\n-B05B Disk Start            0000 (0)\n-B05D Int File Attributes   0000 (0)\n+B125 CENTRAL HEADER #9     02014B50 (33639248)\n+B129 Created Zip Spec      14 (20) '2.0'\n+B12A Created OS            03 (3) 'Unix'\n+B12B Extract Zip Spec      0A (10) '1.0'\n+B12C Extract OS            00 (0) 'MS-DOS'\n+B12D General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+B12F Compression Method    0000 (0) 'Stored'\n+B131 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B135 CRC                   00000000 (0)\n+B139 Compressed Size       00000000 (0)\n+B13D Uncompressed Size     00000000 (0)\n+B141 Filename Length       002B (43)\n+B143 Extra Length          0000 (0)\n+B145 Comment Length        0000 (0)\n+B147 Disk Start            0000 (0)\n+B149 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B05F Ext File Attributes   41ED0010 (1106051088)\n+B14B Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-B063 Local Header Offset   000001C6 (454)\n-B067 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B14F Local Header Offset   000001C6 (454)\n+B153 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB067: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB153: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xB067: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xB153: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xB03F: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB12B: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-B092 CENTRAL HEADER #10    02014B50 (33639248)\n-B096 Created Zip Spec      14 (20) '2.0'\n-B097 Created OS            03 (3) 'Unix'\n-B098 Extract Zip Spec      0A (10) '1.0'\n-B099 Extract OS            00 (0) 'MS-DOS'\n-B09A General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-B09C Compression Method    0000 (0) 'Stored'\n-B09E Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B0A2 CRC                   00000000 (0)\n-B0A6 Compressed Size       00000000 (0)\n-B0AA Uncompressed Size     00000000 (0)\n-B0AE Filename Length       002B (43)\n-B0B0 Extra Length          0000 (0)\n-B0B2 Comment Length        0000 (0)\n-B0B4 Disk Start            0000 (0)\n-B0B6 Int File Attributes   0000 (0)\n+B17E CENTRAL HEADER #10    02014B50 (33639248)\n+B182 Created Zip Spec      14 (20) '2.0'\n+B183 Created OS            03 (3) 'Unix'\n+B184 Extract Zip Spec      0A (10) '1.0'\n+B185 Extract OS            00 (0) 'MS-DOS'\n+B186 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+B188 Compression Method    0000 (0) 'Stored'\n+B18A Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B18E CRC                   00000000 (0)\n+B192 Compressed Size       00000000 (0)\n+B196 Uncompressed Size     00000000 (0)\n+B19A Filename Length       002B (43)\n+B19C Extra Length          0000 (0)\n+B19E Comment Length        0000 (0)\n+B1A0 Disk Start            0000 (0)\n+B1A2 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B0B8 Ext File Attributes   41ED0010 (1106051088)\n+B1A4 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-B0BC Local Header Offset   0000020F (527)\n-B0C0 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B1A8 Local Header Offset   0000020F (527)\n+B1AC Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB0C0: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB1AC: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xB0C0: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xB1AC: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xB098: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB184: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-B0EB CENTRAL HEADER #11    02014B50 (33639248)\n-B0EF Created Zip Spec      14 (20) '2.0'\n-B0F0 Created OS            03 (3) 'Unix'\n-B0F1 Extract Zip Spec      0A (10) '1.0'\n-B0F2 Extract OS            00 (0) 'MS-DOS'\n-B0F3 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-B0F5 Compression Method    0000 (0) 'Stored'\n-B0F7 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B0FB CRC                   00000000 (0)\n-B0FF Compressed Size       00000000 (0)\n-B103 Uncompressed Size     00000000 (0)\n-B107 Filename Length       000F (15)\n-B109 Extra Length          0000 (0)\n-B10B Comment Length        0000 (0)\n-B10D Disk Start            0000 (0)\n-B10F Int File Attributes   0000 (0)\n+B1D7 CENTRAL HEADER #11    02014B50 (33639248)\n+B1DB Created Zip Spec      14 (20) '2.0'\n+B1DC Created OS            03 (3) 'Unix'\n+B1DD Extract Zip Spec      0A (10) '1.0'\n+B1DE Extract OS            00 (0) 'MS-DOS'\n+B1DF General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+B1E1 Compression Method    0000 (0) 'Stored'\n+B1E3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B1E7 CRC                   00000000 (0)\n+B1EB Compressed Size       00000000 (0)\n+B1EF Uncompressed Size     00000000 (0)\n+B1F3 Filename Length       000F (15)\n+B1F5 Extra Length          0000 (0)\n+B1F7 Comment Length        0000 (0)\n+B1F9 Disk Start            0000 (0)\n+B1FB Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B111 Ext File Attributes   41ED0010 (1106051088)\n+B1FD Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-B115 Local Header Offset   00000258 (600)\n-B119 Filename              'XXXXXXXXXXXXXXX'\n+B201 Local Header Offset   00000258 (600)\n+B205 Filename              'XXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB119: Filename 'XXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB205: Filename 'XXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xB119: Directory 'XXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xB205: Directory 'XXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xB0F1: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB1DD: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXX'\n #\n \n-B128 CENTRAL HEADER #12    02014B50 (33639248)\n-B12C Created Zip Spec      14 (20) '2.0'\n-B12D Created OS            03 (3) 'Unix'\n-B12E Extract Zip Spec      0A (10) '1.0'\n-B12F Extract OS            00 (0) 'MS-DOS'\n-B130 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-B132 Compression Method    0000 (0) 'Stored'\n-B134 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B138 CRC                   00000000 (0)\n-B13C Compressed Size       00000000 (0)\n-B140 Uncompressed Size     00000000 (0)\n-B144 Filename Length       0018 (24)\n-B146 Extra Length          0000 (0)\n-B148 Comment Length        0000 (0)\n-B14A Disk Start            0000 (0)\n-B14C Int File Attributes   0000 (0)\n+B214 CENTRAL HEADER #12    02014B50 (33639248)\n+B218 Created Zip Spec      14 (20) '2.0'\n+B219 Created OS            03 (3) 'Unix'\n+B21A Extract Zip Spec      0A (10) '1.0'\n+B21B Extract OS            00 (0) 'MS-DOS'\n+B21C General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+B21E Compression Method    0000 (0) 'Stored'\n+B220 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B224 CRC                   00000000 (0)\n+B228 Compressed Size       00000000 (0)\n+B22C Uncompressed Size     00000000 (0)\n+B230 Filename Length       0018 (24)\n+B232 Extra Length          0000 (0)\n+B234 Comment Length        0000 (0)\n+B236 Disk Start            0000 (0)\n+B238 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B14E Ext File Attributes   41ED0010 (1106051088)\n+B23A Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-B152 Local Header Offset   00000285 (645)\n-B156 Filename              'XXXXXXXXXXXXXXXXXXXXXXXX'\n+B23E Local Header Offset   00000285 (645)\n+B242 Filename              'XXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB156: Filename 'XXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB242: Filename 'XXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xB156: Directory 'XXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xB242: Directory 'XXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xB12E: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB21A: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-B16E CENTRAL HEADER #13    02014B50 (33639248)\n-B172 Created Zip Spec      14 (20) '2.0'\n-B173 Created OS            03 (3) 'Unix'\n-B174 Extract Zip Spec      0A (10) '1.0'\n-B175 Extract OS            00 (0) 'MS-DOS'\n-B176 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-B178 Compression Method    0000 (0) 'Stored'\n-B17A Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B17E CRC                   00000000 (0)\n-B182 Compressed Size       00000000 (0)\n-B186 Uncompressed Size     00000000 (0)\n-B18A Filename Length       000F (15)\n-B18C Extra Length          0000 (0)\n-B18E Comment Length        0000 (0)\n-B190 Disk Start            0000 (0)\n-B192 Int File Attributes   0000 (0)\n+B25A CENTRAL HEADER #13    02014B50 (33639248)\n+B25E Created Zip Spec      14 (20) '2.0'\n+B25F Created OS            03 (3) 'Unix'\n+B260 Extract Zip Spec      0A (10) '1.0'\n+B261 Extract OS            00 (0) 'MS-DOS'\n+B262 General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+B264 Compression Method    0000 (0) 'Stored'\n+B266 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B26A CRC                   00000000 (0)\n+B26E Compressed Size       00000000 (0)\n+B272 Uncompressed Size     00000000 (0)\n+B276 Filename Length       000F (15)\n+B278 Extra Length          0000 (0)\n+B27A Comment Length        0000 (0)\n+B27C Disk Start            0000 (0)\n+B27E Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B194 Ext File Attributes   41ED0010 (1106051088)\n+B280 Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-B198 Local Header Offset   000002BB (699)\n-B19C Filename              'XXXXXXXXXXXXXXX'\n+B284 Local Header Offset   000002BB (699)\n+B288 Filename              'XXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB19C: Filename 'XXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB288: Filename 'XXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xB19C: Directory 'XXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xB288: Directory 'XXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xB174: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB260: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXX'\n #\n \n-B1AB CENTRAL HEADER #14    02014B50 (33639248)\n-B1AF Created Zip Spec      14 (20) '2.0'\n-B1B0 Created OS            03 (3) 'Unix'\n-B1B1 Extract Zip Spec      0A (10) '1.0'\n-B1B2 Extract OS            00 (0) 'MS-DOS'\n-B1B3 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-B1B5 Compression Method    0000 (0) 'Stored'\n-B1B7 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B1BB CRC                   00000000 (0)\n-B1BF Compressed Size       00000000 (0)\n-B1C3 Uncompressed Size     00000000 (0)\n-B1C7 Filename Length       0020 (32)\n-B1C9 Extra Length          0000 (0)\n-B1CB Comment Length        0000 (0)\n-B1CD Disk Start            0000 (0)\n-B1CF Int File Attributes   0000 (0)\n+B297 CENTRAL HEADER #14    02014B50 (33639248)\n+B29B Created Zip Spec      14 (20) '2.0'\n+B29C Created OS            03 (3) 'Unix'\n+B29D Extract Zip Spec      0A (10) '1.0'\n+B29E Extract OS            00 (0) 'MS-DOS'\n+B29F General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+B2A1 Compression Method    0000 (0) 'Stored'\n+B2A3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B2A7 CRC                   00000000 (0)\n+B2AB Compressed Size       00000000 (0)\n+B2AF Uncompressed Size     00000000 (0)\n+B2B3 Filename Length       0020 (32)\n+B2B5 Extra Length          0000 (0)\n+B2B7 Comment Length        0000 (0)\n+B2B9 Disk Start            0000 (0)\n+B2BB Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B1D1 Ext File Attributes   41ED0010 (1106051088)\n+B2BD Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-B1D5 Local Header Offset   000002E8 (744)\n-B1D9 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B2C1 Local Header Offset   000002E8 (744)\n+B2C5 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB1D9: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB2C5: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xB1D9: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xB2C5: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xB1B1: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB29D: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-B1F9 CENTRAL HEADER #15    02014B50 (33639248)\n-B1FD Created Zip Spec      14 (20) '2.0'\n-B1FE Created OS            03 (3) 'Unix'\n-B1FF Extract Zip Spec      0A (10) '1.0'\n-B200 Extract OS            00 (0) 'MS-DOS'\n-B201 General Purpose Flag  0800 (2048)\n-     [Bit 11]              1 'Language Encoding'\n-B203 Compression Method    0000 (0) 'Stored'\n-B205 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B209 CRC                   00000000 (0)\n-B20D Compressed Size       00000000 (0)\n-B211 Uncompressed Size     00000000 (0)\n-B215 Filename Length       0030 (48)\n-B217 Extra Length          0000 (0)\n-B219 Comment Length        0000 (0)\n-B21B Disk Start            0000 (0)\n-B21D Int File Attributes   0000 (0)\n+B2E5 CENTRAL HEADER #15    02014B50 (33639248)\n+B2E9 Created Zip Spec      14 (20) '2.0'\n+B2EA Created OS            03 (3) 'Unix'\n+B2EB Extract Zip Spec      0A (10) '1.0'\n+B2EC Extract OS            00 (0) 'MS-DOS'\n+B2ED General Purpose Flag  0800 (2048)\n+     [Bit 11]              1 'Language Encoding'\n+B2EF Compression Method    0000 (0) 'Stored'\n+B2F1 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B2F5 CRC                   00000000 (0)\n+B2F9 Compressed Size       00000000 (0)\n+B2FD Uncompressed Size     00000000 (0)\n+B301 Filename Length       0030 (48)\n+B303 Extra Length          0000 (0)\n+B305 Comment Length        0000 (0)\n+B307 Disk Start            0000 (0)\n+B309 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B21F Ext File Attributes   41ED0010 (1106051088)\n+B30B Ext File Attributes   41ED0010 (1106051088)\n      [Bit 4]               Directory\n      [Bits 16-24]          01ED (493) 'Unix attrib: rwxr-xr-x'\n      [Bits 28-31]          04 (4) 'Directory'\n-B223 Local Header Offset   00000326 (806)\n-B227 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B30F Local Header Offset   00000326 (806)\n+B313 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB227: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB313: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n-# ERROR: Offset 0xB227: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n+# ERROR: Offset 0xB313: Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' must end in a '/'\n #        'External Attributes' flag this as a directory\n #\n-# WARNING: Offset 0xB1FF: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB2EB: 'Extract Zip Spec' is '1.0'. Need value >= '2.0' for Directory 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n \n-B257 CENTRAL HEADER #16    02014B50 (33639248)\n-B25B Created Zip Spec      14 (20) '2.0'\n-B25C Created OS            03 (3) 'Unix'\n-B25D Extract Zip Spec      14 (20) '2.0'\n-B25E Extract OS            00 (0) 'MS-DOS'\n-B25F General Purpose Flag  0800 (2048)\n+B343 CENTRAL HEADER #16    02014B50 (33639248)\n+B347 Created Zip Spec      14 (20) '2.0'\n+B348 Created OS            03 (3) 'Unix'\n+B349 Extract Zip Spec      14 (20) '2.0'\n+B34A Extract OS            00 (0) 'MS-DOS'\n+B34B General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B261 Compression Method    0008 (8) 'Deflated'\n-B263 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B267 CRC                   CFC19B47 (3485571911)\n-B26B Compressed Size       00000307 (775)\n-B26F Uncompressed Size     00000C40 (3136)\n-B273 Filename Length       0015 (21)\n-B275 Extra Length          0000 (0)\n-B277 Comment Length        0000 (0)\n-B279 Disk Start            0000 (0)\n-B27B Int File Attributes   0000 (0)\n+B34D Compression Method    0008 (8) 'Deflated'\n+B34F Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B353 CRC                   CFC19B47 (3485571911)\n+B357 Compressed Size       00000307 (775)\n+B35B Uncompressed Size     00000C40 (3136)\n+B35F Filename Length       0015 (21)\n+B361 Extra Length          0000 (0)\n+B363 Comment Length        0000 (0)\n+B365 Disk Start            0000 (0)\n+B367 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B27D Ext File Attributes   81A40000 (2175008768)\n+B369 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B281 Local Header Offset   00000374 (884)\n-B285 Filename              'XXXXXXXXXXXXXXXXXXXXX'\n+B36D Local Header Offset   00000374 (884)\n+B371 Filename              'XXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB285: Filename 'XXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB371: Filename 'XXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B29A CENTRAL HEADER #17    02014B50 (33639248)\n-B29E Created Zip Spec      14 (20) '2.0'\n-B29F Created OS            03 (3) 'Unix'\n-B2A0 Extract Zip Spec      14 (20) '2.0'\n-B2A1 Extract OS            00 (0) 'MS-DOS'\n-B2A2 General Purpose Flag  0800 (2048)\n+B386 CENTRAL HEADER #17    02014B50 (33639248)\n+B38A Created Zip Spec      14 (20) '2.0'\n+B38B Created OS            03 (3) 'Unix'\n+B38C Extract Zip Spec      14 (20) '2.0'\n+B38D Extract OS            00 (0) 'MS-DOS'\n+B38E General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B2A4 Compression Method    0008 (8) 'Deflated'\n-B2A6 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B2AA CRC                   86E2B4B4 (2263004340)\n-B2AE Compressed Size       00000F6D (3949)\n-B2B2 Uncompressed Size     00002C5E (11358)\n-B2B6 Filename Length       0010 (16)\n-B2B8 Extra Length          0000 (0)\n-B2BA Comment Length        0000 (0)\n-B2BC Disk Start            0000 (0)\n-B2BE Int File Attributes   0000 (0)\n+B390 Compression Method    0008 (8) 'Deflated'\n+B392 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B396 CRC                   86E2B4B4 (2263004340)\n+B39A Compressed Size       00000F6D (3949)\n+B39E Uncompressed Size     00002C5E (11358)\n+B3A2 Filename Length       0010 (16)\n+B3A4 Extra Length          0000 (0)\n+B3A6 Comment Length        0000 (0)\n+B3A8 Disk Start            0000 (0)\n+B3AA Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B2C0 Ext File Attributes   81A40000 (2175008768)\n+B3AC Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B2C4 Local Header Offset   000006AE (1710)\n-B2C8 Filename              'XXXXXXXXXXXXXXXX'\n+B3B0 Local Header Offset   000006AE (1710)\n+B3B4 Filename              'XXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB2C8: Filename 'XXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB3B4: Filename 'XXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B2D8 CENTRAL HEADER #18    02014B50 (33639248)\n-B2DC Created Zip Spec      14 (20) '2.0'\n-B2DD Created OS            03 (3) 'Unix'\n-B2DE Extract Zip Spec      14 (20) '2.0'\n-B2DF Extract OS            00 (0) 'MS-DOS'\n-B2E0 General Purpose Flag  0800 (2048)\n+B3C4 CENTRAL HEADER #18    02014B50 (33639248)\n+B3C8 Created Zip Spec      14 (20) '2.0'\n+B3C9 Created OS            03 (3) 'Unix'\n+B3CA Extract Zip Spec      14 (20) '2.0'\n+B3CB Extract OS            00 (0) 'MS-DOS'\n+B3CC General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B2E2 Compression Method    0008 (8) 'Deflated'\n-B2E4 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B2E8 CRC                   9C935012 (2626899986)\n-B2EC Compressed Size       0000007B (123)\n-B2F0 Uncompressed Size     000000AC (172)\n-B2F4 Filename Length       000F (15)\n-B2F6 Extra Length          0000 (0)\n-B2F8 Comment Length        0000 (0)\n-B2FA Disk Start            0000 (0)\n-B2FC Int File Attributes   0000 (0)\n+B3CE Compression Method    0008 (8) 'Deflated'\n+B3D0 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B3D4 CRC                   9C935012 (2626899986)\n+B3D8 Compressed Size       0000007B (123)\n+B3DC Uncompressed Size     000000AC (172)\n+B3E0 Filename Length       000F (15)\n+B3E2 Extra Length          0000 (0)\n+B3E4 Comment Length        0000 (0)\n+B3E6 Disk Start            0000 (0)\n+B3E8 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B2FE Ext File Attributes   81A40000 (2175008768)\n+B3EA Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B302 Local Header Offset   00001649 (5705)\n-B306 Filename              'XXXXXXXXXXXXXXX'\n+B3EE Local Header Offset   00001649 (5705)\n+B3F2 Filename              'XXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB306: Filename 'XXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB3F2: Filename 'XXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B315 CENTRAL HEADER #19    02014B50 (33639248)\n-B319 Created Zip Spec      14 (20) '2.0'\n-B31A Created OS            03 (3) 'Unix'\n-B31B Extract Zip Spec      14 (20) '2.0'\n-B31C Extract OS            00 (0) 'MS-DOS'\n-B31D General Purpose Flag  0800 (2048)\n+B401 CENTRAL HEADER #19    02014B50 (33639248)\n+B405 Created Zip Spec      14 (20) '2.0'\n+B406 Created OS            03 (3) 'Unix'\n+B407 Extract Zip Spec      14 (20) '2.0'\n+B408 Extract OS            00 (0) 'MS-DOS'\n+B409 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B31F Compression Method    0008 (8) 'Deflated'\n-B321 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B325 CRC                   B7F8FDDA (3086548442)\n-B329 Compressed Size       00000EEE (3822)\n-B32D Uncompressed Size     00003E47 (15943)\n-B331 Filename Length       003D (61)\n-B333 Extra Length          0000 (0)\n-B335 Comment Length        0000 (0)\n-B337 Disk Start            0000 (0)\n-B339 Int File Attributes   0000 (0)\n+B40B Compression Method    0008 (8) 'Deflated'\n+B40D Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B411 CRC                   5F5E6ACD (1600023245)\n+B415 Compressed Size       00000F00 (3840)\n+B419 Uncompressed Size     00003F85 (16261)\n+B41D Filename Length       003D (61)\n+B41F Extra Length          0000 (0)\n+B421 Comment Length        0000 (0)\n+B423 Disk Start            0000 (0)\n+B425 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B33B Ext File Attributes   81A40000 (2175008768)\n+B427 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B33F Local Header Offset   000016F1 (5873)\n-B343 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B42B Local Header Offset   000016F1 (5873)\n+B42F Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB343: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB42F: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B380 CENTRAL HEADER #20    02014B50 (33639248)\n-B384 Created Zip Spec      14 (20) '2.0'\n-B385 Created OS            03 (3) 'Unix'\n-B386 Extract Zip Spec      14 (20) '2.0'\n-B387 Extract OS            00 (0) 'MS-DOS'\n-B388 General Purpose Flag  0800 (2048)\n+B46C CENTRAL HEADER #20    02014B50 (33639248)\n+B470 Created Zip Spec      14 (20) '2.0'\n+B471 Created OS            03 (3) 'Unix'\n+B472 Extract Zip Spec      14 (20) '2.0'\n+B473 Extract OS            00 (0) 'MS-DOS'\n+B474 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B38A Compression Method    0008 (8) 'Deflated'\n-B38C Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B390 CRC                   03D1B931 (64076081)\n-B394 Compressed Size       00000748 (1864)\n-B398 Uncompressed Size     000018E3 (6371)\n-B39C Filename Length       003E (62)\n-B39E Extra Length          0000 (0)\n-B3A0 Comment Length        0000 (0)\n-B3A2 Disk Start            0000 (0)\n-B3A4 Int File Attributes   0000 (0)\n+B476 Compression Method    0008 (8) 'Deflated'\n+B478 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B47C CRC                   980C94D0 (2550961360)\n+B480 Compressed Size       00000755 (1877)\n+B484 Uncompressed Size     0000199A (6554)\n+B488 Filename Length       003E (62)\n+B48A Extra Length          0000 (0)\n+B48C Comment Length        0000 (0)\n+B48E Disk Start            0000 (0)\n+B490 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B3A6 Ext File Attributes   81A40000 (2175008768)\n+B492 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B3AA Local Header Offset   0000263A (9786)\n-B3AE Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B496 Local Header Offset   0000264C (9804)\n+B49A Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB3AE: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB49A: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B3EC CENTRAL HEADER #21    02014B50 (33639248)\n-B3F0 Created Zip Spec      14 (20) '2.0'\n-B3F1 Created OS            03 (3) 'Unix'\n-B3F2 Extract Zip Spec      14 (20) '2.0'\n-B3F3 Extract OS            00 (0) 'MS-DOS'\n-B3F4 General Purpose Flag  0800 (2048)\n+B4D8 CENTRAL HEADER #21    02014B50 (33639248)\n+B4DC Created Zip Spec      14 (20) '2.0'\n+B4DD Created OS            03 (3) 'Unix'\n+B4DE Extract Zip Spec      14 (20) '2.0'\n+B4DF Extract OS            00 (0) 'MS-DOS'\n+B4E0 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B3F6 Compression Method    0008 (8) 'Deflated'\n-B3F8 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B3FC CRC                   F93BB070 (4181438576)\n-B400 Compressed Size       000003F3 (1011)\n-B404 Uncompressed Size     000008B8 (2232)\n-B408 Filename Length       0032 (50)\n-B40A Extra Length          0000 (0)\n-B40C Comment Length        0000 (0)\n-B40E Disk Start            0000 (0)\n-B410 Int File Attributes   0000 (0)\n+B4E2 Compression Method    0008 (8) 'Deflated'\n+B4E4 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B4E8 CRC                   4C7D08FC (1283262716)\n+B4EC Compressed Size       000003FD (1021)\n+B4F0 Uncompressed Size     000008FF (2303)\n+B4F4 Filename Length       0032 (50)\n+B4F6 Extra Length          0000 (0)\n+B4F8 Comment Length        0000 (0)\n+B4FA Disk Start            0000 (0)\n+B4FC Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B412 Ext File Attributes   81A40000 (2175008768)\n+B4FE Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B416 Local Header Offset   00002DDE (11742)\n-B41A Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B502 Local Header Offset   00002DFD (11773)\n+B506 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB41A: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB506: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B44C CENTRAL HEADER #22    02014B50 (33639248)\n-B450 Created Zip Spec      14 (20) '2.0'\n-B451 Created OS            03 (3) 'Unix'\n-B452 Extract Zip Spec      14 (20) '2.0'\n-B453 Extract OS            00 (0) 'MS-DOS'\n-B454 General Purpose Flag  0800 (2048)\n+B538 CENTRAL HEADER #22    02014B50 (33639248)\n+B53C Created Zip Spec      14 (20) '2.0'\n+B53D Created OS            03 (3) 'Unix'\n+B53E Extract Zip Spec      14 (20) '2.0'\n+B53F Extract OS            00 (0) 'MS-DOS'\n+B540 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B456 Compression Method    0008 (8) 'Deflated'\n-B458 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B45C CRC                   C7D35A4B (3352517195)\n-B460 Compressed Size       000008E7 (2279)\n-B464 Uncompressed Size     00001F36 (7990)\n-B468 Filename Length       0040 (64)\n-B46A Extra Length          0000 (0)\n-B46C Comment Length        0000 (0)\n-B46E Disk Start            0000 (0)\n-B470 Int File Attributes   0000 (0)\n+B542 Compression Method    0008 (8) 'Deflated'\n+B544 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B548 CRC                   EAE8515F (3941093727)\n+B54C Compressed Size       000008F1 (2289)\n+B550 Uncompressed Size     00001FF9 (8185)\n+B554 Filename Length       0040 (64)\n+B556 Extra Length          0000 (0)\n+B558 Comment Length        0000 (0)\n+B55A Disk Start            0000 (0)\n+B55C Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B472 Ext File Attributes   81A40000 (2175008768)\n+B55E Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B476 Local Header Offset   00003221 (12833)\n-B47A Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B562 Local Header Offset   0000324A (12874)\n+B566 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB47A: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB566: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B4BA CENTRAL HEADER #23    02014B50 (33639248)\n-B4BE Created Zip Spec      14 (20) '2.0'\n-B4BF Created OS            03 (3) 'Unix'\n-B4C0 Extract Zip Spec      14 (20) '2.0'\n-B4C1 Extract OS            00 (0) 'MS-DOS'\n-B4C2 General Purpose Flag  0800 (2048)\n+B5A6 CENTRAL HEADER #23    02014B50 (33639248)\n+B5AA Created Zip Spec      14 (20) '2.0'\n+B5AB Created OS            03 (3) 'Unix'\n+B5AC Extract Zip Spec      14 (20) '2.0'\n+B5AD Extract OS            00 (0) 'MS-DOS'\n+B5AE General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B4C4 Compression Method    0008 (8) 'Deflated'\n-B4C6 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B4CA CRC                   D012E5FC (3490899452)\n-B4CE Compressed Size       000007FD (2045)\n-B4D2 Uncompressed Size     00001BA0 (7072)\n-B4D6 Filename Length       003C (60)\n-B4D8 Extra Length          0000 (0)\n-B4DA Comment Length        0000 (0)\n-B4DC Disk Start            0000 (0)\n-B4DE Int File Attributes   0000 (0)\n+B5B0 Compression Method    0008 (8) 'Deflated'\n+B5B2 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B5B6 CRC                   E202F321 (3791844129)\n+B5BA Compressed Size       0000080B (2059)\n+B5BE Uncompressed Size     00001C58 (7256)\n+B5C2 Filename Length       003C (60)\n+B5C4 Extra Length          0000 (0)\n+B5C6 Comment Length        0000 (0)\n+B5C8 Disk Start            0000 (0)\n+B5CA Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B4E0 Ext File Attributes   81A40000 (2175008768)\n+B5CC Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B4E4 Local Header Offset   00003B66 (15206)\n-B4E8 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B5D0 Local Header Offset   00003B99 (15257)\n+B5D4 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB4E8: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB5D4: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B524 CENTRAL HEADER #24    02014B50 (33639248)\n-B528 Created Zip Spec      14 (20) '2.0'\n-B529 Created OS            03 (3) 'Unix'\n-B52A Extract Zip Spec      14 (20) '2.0'\n-B52B Extract OS            00 (0) 'MS-DOS'\n-B52C General Purpose Flag  0800 (2048)\n+B610 CENTRAL HEADER #24    02014B50 (33639248)\n+B614 Created Zip Spec      14 (20) '2.0'\n+B615 Created OS            03 (3) 'Unix'\n+B616 Extract Zip Spec      14 (20) '2.0'\n+B617 Extract OS            00 (0) 'MS-DOS'\n+B618 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B52E Compression Method    0008 (8) 'Deflated'\n-B530 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B534 CRC                   A6D38CE4 (2798882020)\n-B538 Compressed Size       00000A39 (2617)\n-B53C Uncompressed Size     00002AE7 (10983)\n-B540 Filename Length       0033 (51)\n-B542 Extra Length          0000 (0)\n-B544 Comment Length        0000 (0)\n-B546 Disk Start            0000 (0)\n-B548 Int File Attributes   0000 (0)\n+B61A Compression Method    0008 (8) 'Deflated'\n+B61C Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B620 CRC                   DBBCD787 (3686586247)\n+B624 Compressed Size       00000A4C (2636)\n+B628 Uncompressed Size     00002BDF (11231)\n+B62C Filename Length       0033 (51)\n+B62E Extra Length          0000 (0)\n+B630 Comment Length        0000 (0)\n+B632 Disk Start            0000 (0)\n+B634 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B54A Ext File Attributes   81A40000 (2175008768)\n+B636 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B54E Local Header Offset   000043BD (17341)\n-B552 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B63A Local Header Offset   000043FE (17406)\n+B63E Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB552: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB63E: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B585 CENTRAL HEADER #25    02014B50 (33639248)\n-B589 Created Zip Spec      14 (20) '2.0'\n-B58A Created OS            03 (3) 'Unix'\n-B58B Extract Zip Spec      14 (20) '2.0'\n-B58C Extract OS            00 (0) 'MS-DOS'\n-B58D General Purpose Flag  0800 (2048)\n+B671 CENTRAL HEADER #25    02014B50 (33639248)\n+B675 Created Zip Spec      14 (20) '2.0'\n+B676 Created OS            03 (3) 'Unix'\n+B677 Extract Zip Spec      14 (20) '2.0'\n+B678 Extract OS            00 (0) 'MS-DOS'\n+B679 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B58F Compression Method    0008 (8) 'Deflated'\n-B591 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B595 CRC                   982FC700 (2553267968)\n-B599 Compressed Size       00000370 (880)\n-B59D Uncompressed Size     00000A19 (2585)\n-B5A1 Filename Length       003A (58)\n-B5A3 Extra Length          0000 (0)\n-B5A5 Comment Length        0000 (0)\n-B5A7 Disk Start            0000 (0)\n-B5A9 Int File Attributes   0000 (0)\n+B67B Compression Method    0008 (8) 'Deflated'\n+B67D Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B681 CRC                   E1297FD5 (3777593301)\n+B685 Compressed Size       0000037A (890)\n+B689 Uncompressed Size     00000A4E (2638)\n+B68D Filename Length       003A (58)\n+B68F Extra Length          0000 (0)\n+B691 Comment Length        0000 (0)\n+B693 Disk Start            0000 (0)\n+B695 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B5AB Ext File Attributes   81A40000 (2175008768)\n+B697 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B5AF Local Header Offset   00004E47 (20039)\n-B5B3 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B69B Local Header Offset   00004E9B (20123)\n+B69F Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB5B3: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB69F: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B5ED CENTRAL HEADER #26    02014B50 (33639248)\n-B5F1 Created Zip Spec      14 (20) '2.0'\n-B5F2 Created OS            03 (3) 'Unix'\n-B5F3 Extract Zip Spec      14 (20) '2.0'\n-B5F4 Extract OS            00 (0) 'MS-DOS'\n-B5F5 General Purpose Flag  0800 (2048)\n+B6D9 CENTRAL HEADER #26    02014B50 (33639248)\n+B6DD Created Zip Spec      14 (20) '2.0'\n+B6DE Created OS            03 (3) 'Unix'\n+B6DF Extract Zip Spec      14 (20) '2.0'\n+B6E0 Extract OS            00 (0) 'MS-DOS'\n+B6E1 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B5F7 Compression Method    0008 (8) 'Deflated'\n-B5F9 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B5FD CRC                   C6A73CC6 (3332848838)\n-B601 Compressed Size       0000045E (1118)\n-B605 Uncompressed Size     00000C1E (3102)\n-B609 Filename Length       0038 (56)\n-B60B Extra Length          0000 (0)\n-B60D Comment Length        0000 (0)\n-B60F Disk Start            0000 (0)\n-B611 Int File Attributes   0000 (0)\n+B6E3 Compression Method    0008 (8) 'Deflated'\n+B6E5 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B6E9 CRC                   CDBF443E (3451864126)\n+B6ED Compressed Size       00000466 (1126)\n+B6F1 Uncompressed Size     00000C74 (3188)\n+B6F5 Filename Length       0038 (56)\n+B6F7 Extra Length          0000 (0)\n+B6F9 Comment Length        0000 (0)\n+B6FB Disk Start            0000 (0)\n+B6FD Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B613 Ext File Attributes   81A40000 (2175008768)\n+B6FF Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B617 Local Header Offset   0000520F (21007)\n-B61B Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B703 Local Header Offset   0000526D (21101)\n+B707 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB61B: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB707: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B653 CENTRAL HEADER #27    02014B50 (33639248)\n-B657 Created Zip Spec      14 (20) '2.0'\n-B658 Created OS            03 (3) 'Unix'\n-B659 Extract Zip Spec      14 (20) '2.0'\n-B65A Extract OS            00 (0) 'MS-DOS'\n-B65B General Purpose Flag  0800 (2048)\n+B73F CENTRAL HEADER #27    02014B50 (33639248)\n+B743 Created Zip Spec      14 (20) '2.0'\n+B744 Created OS            03 (3) 'Unix'\n+B745 Extract Zip Spec      14 (20) '2.0'\n+B746 Extract OS            00 (0) 'MS-DOS'\n+B747 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B65D Compression Method    0008 (8) 'Deflated'\n-B65F Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B663 CRC                   94899E78 (2492046968)\n-B667 Compressed Size       000002B3 (691)\n-B66B Uncompressed Size     000005B1 (1457)\n-B66F Filename Length       0036 (54)\n-B671 Extra Length          0000 (0)\n-B673 Comment Length        0000 (0)\n-B675 Disk Start            0000 (0)\n-B677 Int File Attributes   0000 (0)\n+B749 Compression Method    0008 (8) 'Deflated'\n+B74B Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B74F CRC                   151E182C (354293804)\n+B753 Compressed Size       000002BC (700)\n+B757 Uncompressed Size     000005DD (1501)\n+B75B Filename Length       0036 (54)\n+B75D Extra Length          0000 (0)\n+B75F Comment Length        0000 (0)\n+B761 Disk Start            0000 (0)\n+B763 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B679 Ext File Attributes   81A40000 (2175008768)\n+B765 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B67D Local Header Offset   000056C3 (22211)\n-B681 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B769 Local Header Offset   00005729 (22313)\n+B76D Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB681: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB76D: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B6B7 CENTRAL HEADER #28    02014B50 (33639248)\n-B6BB Created Zip Spec      14 (20) '2.0'\n-B6BC Created OS            03 (3) 'Unix'\n-B6BD Extract Zip Spec      14 (20) '2.0'\n-B6BE Extract OS            00 (0) 'MS-DOS'\n-B6BF General Purpose Flag  0800 (2048)\n+B7A3 CENTRAL HEADER #28    02014B50 (33639248)\n+B7A7 Created Zip Spec      14 (20) '2.0'\n+B7A8 Created OS            03 (3) 'Unix'\n+B7A9 Extract Zip Spec      14 (20) '2.0'\n+B7AA Extract OS            00 (0) 'MS-DOS'\n+B7AB General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B6C1 Compression Method    0008 (8) 'Deflated'\n-B6C3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B6C7 CRC                   4247D839 (1112004665)\n-B6CB Compressed Size       00000956 (2390)\n-B6CF Uncompressed Size     00001FD9 (8153)\n-B6D3 Filename Length       0035 (53)\n-B6D5 Extra Length          0000 (0)\n-B6D7 Comment Length        0000 (0)\n-B6D9 Disk Start            0000 (0)\n-B6DB Int File Attributes   0000 (0)\n+B7AD Compression Method    0008 (8) 'Deflated'\n+B7AF Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B7B3 CRC                   39CBA339 (969646905)\n+B7B7 Compressed Size       00000962 (2402)\n+B7BB Uncompressed Size     00002090 (8336)\n+B7BF Filename Length       0035 (53)\n+B7C1 Extra Length          0000 (0)\n+B7C3 Comment Length        0000 (0)\n+B7C5 Disk Start            0000 (0)\n+B7C7 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B6DD Ext File Attributes   81A40000 (2175008768)\n+B7C9 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B6E1 Local Header Offset   000059CA (22986)\n-B6E5 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B7CD Local Header Offset   00005A39 (23097)\n+B7D1 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB6E5: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB7D1: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B71A CENTRAL HEADER #29    02014B50 (33639248)\n-B71E Created Zip Spec      14 (20) '2.0'\n-B71F Created OS            03 (3) 'Unix'\n-B720 Extract Zip Spec      14 (20) '2.0'\n-B721 Extract OS            00 (0) 'MS-DOS'\n-B722 General Purpose Flag  0800 (2048)\n+B806 CENTRAL HEADER #29    02014B50 (33639248)\n+B80A Created Zip Spec      14 (20) '2.0'\n+B80B Created OS            03 (3) 'Unix'\n+B80C Extract Zip Spec      14 (20) '2.0'\n+B80D Extract OS            00 (0) 'MS-DOS'\n+B80E General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B724 Compression Method    0008 (8) 'Deflated'\n-B726 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B72A CRC                   C2B511E4 (3266646500)\n-B72E Compressed Size       00001872 (6258)\n-B732 Uncompressed Size     00006B37 (27447)\n-B736 Filename Length       0036 (54)\n-B738 Extra Length          0000 (0)\n-B73A Comment Length        0000 (0)\n-B73C Disk Start            0000 (0)\n-B73E Int File Attributes   0000 (0)\n+B810 Compression Method    0008 (8) 'Deflated'\n+B812 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B816 CRC                   07C16F02 (130117378)\n+B81A Compressed Size       00001890 (6288)\n+B81E Uncompressed Size     00006DE5 (28133)\n+B822 Filename Length       0036 (54)\n+B824 Extra Length          0000 (0)\n+B826 Comment Length        0000 (0)\n+B828 Disk Start            0000 (0)\n+B82A Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B740 Ext File Attributes   81A40000 (2175008768)\n+B82C Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B744 Local Header Offset   00006373 (25459)\n-B748 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B830 Local Header Offset   000063EE (25582)\n+B834 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB748: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB834: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B77E CENTRAL HEADER #30    02014B50 (33639248)\n-B782 Created Zip Spec      14 (20) '2.0'\n-B783 Created OS            03 (3) 'Unix'\n-B784 Extract Zip Spec      14 (20) '2.0'\n-B785 Extract OS            00 (0) 'MS-DOS'\n-B786 General Purpose Flag  0800 (2048)\n+B86A CENTRAL HEADER #30    02014B50 (33639248)\n+B86E Created Zip Spec      14 (20) '2.0'\n+B86F Created OS            03 (3) 'Unix'\n+B870 Extract Zip Spec      14 (20) '2.0'\n+B871 Extract OS            00 (0) 'MS-DOS'\n+B872 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B788 Compression Method    0008 (8) 'Deflated'\n-B78A Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B78E CRC                   7317DB5C (1930943324)\n-B792 Compressed Size       000002DB (731)\n-B796 Uncompressed Size     00000714 (1812)\n-B79A Filename Length       003C (60)\n-B79C Extra Length          0000 (0)\n-B79E Comment Length        0000 (0)\n-B7A0 Disk Start            0000 (0)\n-B7A2 Int File Attributes   0000 (0)\n+B874 Compression Method    0008 (8) 'Deflated'\n+B876 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B87A CRC                   DA119291 (3658584721)\n+B87E Compressed Size       000002E4 (740)\n+B882 Uncompressed Size     00000752 (1874)\n+B886 Filename Length       003C (60)\n+B888 Extra Length          0000 (0)\n+B88A Comment Length        0000 (0)\n+B88C Disk Start            0000 (0)\n+B88E Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B7A4 Ext File Attributes   81A40000 (2175008768)\n+B890 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B7A8 Local Header Offset   00007C39 (31801)\n-B7AC Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B894 Local Header Offset   00007CD2 (31954)\n+B898 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB7AC: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB898: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B7E8 CENTRAL HEADER #31    02014B50 (33639248)\n-B7EC Created Zip Spec      14 (20) '2.0'\n-B7ED Created OS            03 (3) 'Unix'\n-B7EE Extract Zip Spec      14 (20) '2.0'\n-B7EF Extract OS            00 (0) 'MS-DOS'\n-B7F0 General Purpose Flag  0800 (2048)\n+B8D4 CENTRAL HEADER #31    02014B50 (33639248)\n+B8D8 Created Zip Spec      14 (20) '2.0'\n+B8D9 Created OS            03 (3) 'Unix'\n+B8DA Extract Zip Spec      14 (20) '2.0'\n+B8DB Extract OS            00 (0) 'MS-DOS'\n+B8DC General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B7F2 Compression Method    0008 (8) 'Deflated'\n-B7F4 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B7F8 CRC                   344C1E36 (877403702)\n-B7FC Compressed Size       00000817 (2071)\n-B800 Uncompressed Size     00001FCC (8140)\n-B804 Filename Length       0042 (66)\n-B806 Extra Length          0000 (0)\n-B808 Comment Length        0000 (0)\n-B80A Disk Start            0000 (0)\n-B80C Int File Attributes   0000 (0)\n+B8DE Compression Method    0008 (8) 'Deflated'\n+B8E0 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B8E4 CRC                   0574FE58 (91553368)\n+B8E8 Compressed Size       0000082B (2091)\n+B8EC Uncompressed Size     000020D9 (8409)\n+B8F0 Filename Length       0042 (66)\n+B8F2 Extra Length          0000 (0)\n+B8F4 Comment Length        0000 (0)\n+B8F6 Disk Start            0000 (0)\n+B8F8 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B80E Ext File Attributes   81A40000 (2175008768)\n+B8FA Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B812 Local Header Offset   00007F6E (32622)\n-B816 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B8FE Local Header Offset   00008010 (32784)\n+B902 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB816: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB902: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B858 CENTRAL HEADER #32    02014B50 (33639248)\n-B85C Created Zip Spec      14 (20) '2.0'\n-B85D Created OS            03 (3) 'Unix'\n-B85E Extract Zip Spec      14 (20) '2.0'\n-B85F Extract OS            00 (0) 'MS-DOS'\n-B860 General Purpose Flag  0800 (2048)\n+B944 CENTRAL HEADER #32    02014B50 (33639248)\n+B948 Created Zip Spec      14 (20) '2.0'\n+B949 Created OS            03 (3) 'Unix'\n+B94A Extract Zip Spec      14 (20) '2.0'\n+B94B Extract OS            00 (0) 'MS-DOS'\n+B94C General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B862 Compression Method    0008 (8) 'Deflated'\n-B864 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B868 CRC                   3B14B127 (991211815)\n-B86C Compressed Size       000006AF (1711)\n-B870 Uncompressed Size     000017C7 (6087)\n-B874 Filename Length       0045 (69)\n-B876 Extra Length          0000 (0)\n-B878 Comment Length        0000 (0)\n-B87A Disk Start            0000 (0)\n-B87C Int File Attributes   0000 (0)\n+B94E Compression Method    0008 (8) 'Deflated'\n+B950 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B954 CRC                   B5644E62 (3043249762)\n+B958 Compressed Size       000006BD (1725)\n+B95C Uncompressed Size     0000189A (6298)\n+B960 Filename Length       0045 (69)\n+B962 Extra Length          0000 (0)\n+B964 Comment Length        0000 (0)\n+B966 Disk Start            0000 (0)\n+B968 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B87E Ext File Attributes   81A40000 (2175008768)\n+B96A Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B882 Local Header Offset   000087E5 (34789)\n-B886 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B96E Local Header Offset   0000889B (34971)\n+B972 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB886: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB972: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B8CB CENTRAL HEADER #33    02014B50 (33639248)\n-B8CF Created Zip Spec      14 (20) '2.0'\n-B8D0 Created OS            03 (3) 'Unix'\n-B8D1 Extract Zip Spec      14 (20) '2.0'\n-B8D2 Extract OS            00 (0) 'MS-DOS'\n-B8D3 General Purpose Flag  0800 (2048)\n+B9B7 CENTRAL HEADER #33    02014B50 (33639248)\n+B9BB Created Zip Spec      14 (20) '2.0'\n+B9BC Created OS            03 (3) 'Unix'\n+B9BD Extract Zip Spec      14 (20) '2.0'\n+B9BE Extract OS            00 (0) 'MS-DOS'\n+B9BF General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B8D5 Compression Method    0008 (8) 'Deflated'\n-B8D7 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B8DB CRC                   1915FFAE (420872110)\n-B8DF Compressed Size       000007CC (1996)\n-B8E3 Uncompressed Size     00002228 (8744)\n-B8E7 Filename Length       003C (60)\n-B8E9 Extra Length          0000 (0)\n-B8EB Comment Length        0000 (0)\n-B8ED Disk Start            0000 (0)\n-B8EF Int File Attributes   0000 (0)\n+B9C1 Compression Method    0008 (8) 'Deflated'\n+B9C3 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+B9C7 CRC                   45086F19 (1158180633)\n+B9CB Compressed Size       000007DA (2010)\n+B9CF Uncompressed Size     000022F3 (8947)\n+B9D3 Filename Length       003C (60)\n+B9D5 Extra Length          0000 (0)\n+B9D7 Comment Length        0000 (0)\n+B9D9 Disk Start            0000 (0)\n+B9DB Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B8F1 Ext File Attributes   81A40000 (2175008768)\n+B9DD Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B8F5 Local Header Offset   00008EF7 (36599)\n-B8F9 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+B9E1 Local Header Offset   00008FBB (36795)\n+B9E5 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB8F9: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xB9E5: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B935 CENTRAL HEADER #34    02014B50 (33639248)\n-B939 Created Zip Spec      14 (20) '2.0'\n-B93A Created OS            03 (3) 'Unix'\n-B93B Extract Zip Spec      14 (20) '2.0'\n-B93C Extract OS            00 (0) 'MS-DOS'\n-B93D General Purpose Flag  0800 (2048)\n+BA21 CENTRAL HEADER #34    02014B50 (33639248)\n+BA25 Created Zip Spec      14 (20) '2.0'\n+BA26 Created OS            03 (3) 'Unix'\n+BA27 Extract Zip Spec      14 (20) '2.0'\n+BA28 Extract OS            00 (0) 'MS-DOS'\n+BA29 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B93F Compression Method    0008 (8) 'Deflated'\n-B941 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B945 CRC                   B4BC5053 (3032240211)\n-B949 Compressed Size       00000685 (1669)\n-B94D Uncompressed Size     00001648 (5704)\n-B951 Filename Length       003B (59)\n-B953 Extra Length          0000 (0)\n-B955 Comment Length        0000 (0)\n-B957 Disk Start            0000 (0)\n-B959 Int File Attributes   0000 (0)\n+BA2B Compression Method    0008 (8) 'Deflated'\n+BA2D Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+BA31 CRC                   57E4B8CF (1474607311)\n+BA35 Compressed Size       0000068F (1679)\n+BA39 Uncompressed Size     000016C7 (5831)\n+BA3D Filename Length       003B (59)\n+BA3F Extra Length          0000 (0)\n+BA41 Comment Length        0000 (0)\n+BA43 Disk Start            0000 (0)\n+BA45 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B95B Ext File Attributes   81A40000 (2175008768)\n+BA47 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B95F Local Header Offset   0000971D (38685)\n-B963 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+BA4B Local Header Offset   000097EF (38895)\n+BA4F Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB963: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xBA4F: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-B99E CENTRAL HEADER #35    02014B50 (33639248)\n-B9A2 Created Zip Spec      14 (20) '2.0'\n-B9A3 Created OS            03 (3) 'Unix'\n-B9A4 Extract Zip Spec      14 (20) '2.0'\n-B9A5 Extract OS            00 (0) 'MS-DOS'\n-B9A6 General Purpose Flag  0800 (2048)\n+BA8A CENTRAL HEADER #35    02014B50 (33639248)\n+BA8E Created Zip Spec      14 (20) '2.0'\n+BA8F Created OS            03 (3) 'Unix'\n+BA90 Extract Zip Spec      14 (20) '2.0'\n+BA91 Extract OS            00 (0) 'MS-DOS'\n+BA92 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-B9A8 Compression Method    0008 (8) 'Deflated'\n-B9AA Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-B9AE CRC                   C9453D78 (3376758136)\n-B9B2 Compressed Size       0000038D (909)\n-B9B6 Uncompressed Size     000008E4 (2276)\n-B9BA Filename Length       0043 (67)\n-B9BC Extra Length          0000 (0)\n-B9BE Comment Length        0000 (0)\n-B9C0 Disk Start            0000 (0)\n-B9C2 Int File Attributes   0000 (0)\n+BA94 Compression Method    0008 (8) 'Deflated'\n+BA96 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+BA9A CRC                   A77D588D (2810009741)\n+BA9E Compressed Size       00000398 (920)\n+BAA2 Uncompressed Size     00000921 (2337)\n+BAA6 Filename Length       0043 (67)\n+BAA8 Extra Length          0000 (0)\n+BAAA Comment Length        0000 (0)\n+BAAC Disk Start            0000 (0)\n+BAAE Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-B9C4 Ext File Attributes   81A40000 (2175008768)\n+BAB0 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-B9C8 Local Header Offset   00009DFB (40443)\n-B9CC Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+BAB4 Local Header Offset   00009ED7 (40663)\n+BAB8 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xB9CC: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xBAB8: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-BA0F CENTRAL HEADER #36    02014B50 (33639248)\n-BA13 Created Zip Spec      14 (20) '2.0'\n-BA14 Created OS            03 (3) 'Unix'\n-BA15 Extract Zip Spec      14 (20) '2.0'\n-BA16 Extract OS            00 (0) 'MS-DOS'\n-BA17 General Purpose Flag  0800 (2048)\n+BAFB CENTRAL HEADER #36    02014B50 (33639248)\n+BAFF Created Zip Spec      14 (20) '2.0'\n+BB00 Created OS            03 (3) 'Unix'\n+BB01 Extract Zip Spec      14 (20) '2.0'\n+BB02 Extract OS            00 (0) 'MS-DOS'\n+BB03 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-BA19 Compression Method    0008 (8) 'Deflated'\n-BA1B Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-BA1F CRC                   5A226E99 (1512205977)\n-BA23 Compressed Size       00000465 (1125)\n-BA27 Uncompressed Size     00000B86 (2950)\n-BA2B Filename Length       0047 (71)\n-BA2D Extra Length          0000 (0)\n-BA2F Comment Length        0000 (0)\n-BA31 Disk Start            0000 (0)\n-BA33 Int File Attributes   0000 (0)\n+BB05 Compression Method    0008 (8) 'Deflated'\n+BB07 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+BB0B CRC                   DF443A2F (3745790511)\n+BB0F Compressed Size       00000471 (1137)\n+BB13 Uncompressed Size     00000BC9 (3017)\n+BB17 Filename Length       0047 (71)\n+BB19 Extra Length          0000 (0)\n+BB1B Comment Length        0000 (0)\n+BB1D Disk Start            0000 (0)\n+BB1F Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-BA35 Ext File Attributes   81A40000 (2175008768)\n+BB21 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-BA39 Local Header Offset   0000A1E9 (41449)\n-BA3D Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+BB25 Local Header Offset   0000A2D0 (41680)\n+BB29 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xBA3D: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xBB29: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-BA84 CENTRAL HEADER #37    02014B50 (33639248)\n-BA88 Created Zip Spec      14 (20) '2.0'\n-BA89 Created OS            03 (3) 'Unix'\n-BA8A Extract Zip Spec      14 (20) '2.0'\n-BA8B Extract OS            00 (0) 'MS-DOS'\n-BA8C General Purpose Flag  0800 (2048)\n+BB70 CENTRAL HEADER #37    02014B50 (33639248)\n+BB74 Created Zip Spec      14 (20) '2.0'\n+BB75 Created OS            03 (3) 'Unix'\n+BB76 Extract Zip Spec      14 (20) '2.0'\n+BB77 Extract OS            00 (0) 'MS-DOS'\n+BB78 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-BA8E Compression Method    0008 (8) 'Deflated'\n-BA90 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-BA94 CRC                   2D68A65E (761833054)\n-BA98 Compressed Size       00000052 (82)\n-BA9C Uncompressed Size     00000094 (148)\n-BAA0 Filename Length       0044 (68)\n-BAA2 Extra Length          0000 (0)\n-BAA4 Comment Length        0000 (0)\n-BAA6 Disk Start            0000 (0)\n-BAA8 Int File Attributes   0000 (0)\n+BB7A Compression Method    0008 (8) 'Deflated'\n+BB7C Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+BB80 CRC                   2D68A65E (761833054)\n+BB84 Compressed Size       00000052 (82)\n+BB88 Uncompressed Size     00000094 (148)\n+BB8C Filename Length       0044 (68)\n+BB8E Extra Length          0000 (0)\n+BB90 Comment Length        0000 (0)\n+BB92 Disk Start            0000 (0)\n+BB94 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-BAAA Ext File Attributes   81A40000 (2175008768)\n+BB96 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-BAAE Local Header Offset   0000A6B3 (42675)\n-BAB2 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+BB9A Local Header Offset   0000A7A6 (42918)\n+BB9E Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xBAB2: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xBB9E: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-BAF6 CENTRAL HEADER #38    02014B50 (33639248)\n-BAFA Created Zip Spec      14 (20) '2.0'\n-BAFB Created OS            03 (3) 'Unix'\n-BAFC Extract Zip Spec      14 (20) '2.0'\n-BAFD Extract OS            00 (0) 'MS-DOS'\n-BAFE General Purpose Flag  0800 (2048)\n+BBE2 CENTRAL HEADER #38    02014B50 (33639248)\n+BBE6 Created Zip Spec      14 (20) '2.0'\n+BBE7 Created OS            03 (3) 'Unix'\n+BBE8 Extract Zip Spec      14 (20) '2.0'\n+BBE9 Extract OS            00 (0) 'MS-DOS'\n+BBEA General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-BB00 Compression Method    0008 (8) 'Deflated'\n-BB02 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-BB06 CRC                   A5009E2B (2768281131)\n-BB0A Compressed Size       00000031 (49)\n-BB0E Uncompressed Size     00000039 (57)\n-BB12 Filename Length       0038 (56)\n-BB14 Extra Length          0000 (0)\n-BB16 Comment Length        0000 (0)\n-BB18 Disk Start            0000 (0)\n-BB1A Int File Attributes   0000 (0)\n+BBEC Compression Method    0008 (8) 'Deflated'\n+BBEE Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+BBF2 CRC                   A5009E2B (2768281131)\n+BBF6 Compressed Size       00000031 (49)\n+BBFA Uncompressed Size     00000039 (57)\n+BBFE Filename Length       0038 (56)\n+BC00 Extra Length          0000 (0)\n+BC02 Comment Length        0000 (0)\n+BC04 Disk Start            0000 (0)\n+BC06 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-BB1C Ext File Attributes   81A40000 (2175008768)\n+BC08 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-BB20 Local Header Offset   0000A767 (42855)\n-BB24 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+BC0C Local Header Offset   0000A85A (43098)\n+BC10 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xBB24: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xBC10: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-BB5C CENTRAL HEADER #39    02014B50 (33639248)\n-BB60 Created Zip Spec      14 (20) '2.0'\n-BB61 Created OS            03 (3) 'Unix'\n-BB62 Extract Zip Spec      14 (20) '2.0'\n-BB63 Extract OS            00 (0) 'MS-DOS'\n-BB64 General Purpose Flag  0800 (2048)\n+BC48 CENTRAL HEADER #39    02014B50 (33639248)\n+BC4C Created Zip Spec      14 (20) '2.0'\n+BC4D Created OS            03 (3) 'Unix'\n+BC4E Extract Zip Spec      14 (20) '2.0'\n+BC4F Extract OS            00 (0) 'MS-DOS'\n+BC50 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-BB66 Compression Method    0008 (8) 'Deflated'\n-BB68 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-BB6C CRC                   A3C6F966 (2747726182)\n-BB70 Compressed Size       00000042 (66)\n-BB74 Uncompressed Size     0000007C (124)\n-BB78 Filename Length       0033 (51)\n-BB7A Extra Length          0000 (0)\n-BB7C Comment Length        0000 (0)\n-BB7E Disk Start            0000 (0)\n-BB80 Int File Attributes   0000 (0)\n+BC52 Compression Method    0008 (8) 'Deflated'\n+BC54 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+BC58 CRC                   A3C6F966 (2747726182)\n+BC5C Compressed Size       00000042 (66)\n+BC60 Uncompressed Size     0000007C (124)\n+BC64 Filename Length       0033 (51)\n+BC66 Extra Length          0000 (0)\n+BC68 Comment Length        0000 (0)\n+BC6A Disk Start            0000 (0)\n+BC6C Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-BB82 Ext File Attributes   81A40000 (2175008768)\n+BC6E Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-BB86 Local Header Offset   0000A7EE (42990)\n-BB8A Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+BC72 Local Header Offset   0000A8E1 (43233)\n+BC76 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xBB8A: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xBC76: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-BBBD CENTRAL HEADER #40    02014B50 (33639248)\n-BBC1 Created Zip Spec      14 (20) '2.0'\n-BBC2 Created OS            03 (3) 'Unix'\n-BBC3 Extract Zip Spec      14 (20) '2.0'\n-BBC4 Extract OS            00 (0) 'MS-DOS'\n-BBC5 General Purpose Flag  0800 (2048)\n+BCA9 CENTRAL HEADER #40    02014B50 (33639248)\n+BCAD Created Zip Spec      14 (20) '2.0'\n+BCAE Created OS            03 (3) 'Unix'\n+BCAF Extract Zip Spec      14 (20) '2.0'\n+BCB0 Extract OS            00 (0) 'MS-DOS'\n+BCB1 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-BBC7 Compression Method    0008 (8) 'Deflated'\n-BBC9 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-BBCD CRC                   83A37AD0 (2208529104)\n-BBD1 Compressed Size       0000002A (42)\n-BBD5 Uncompressed Size     00000037 (55)\n-BBD9 Filename Length       0035 (53)\n-BBDB Extra Length          0000 (0)\n-BBDD Comment Length        0000 (0)\n-BBDF Disk Start            0000 (0)\n-BBE1 Int File Attributes   0000 (0)\n+BCB3 Compression Method    0008 (8) 'Deflated'\n+BCB5 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+BCB9 CRC                   83A37AD0 (2208529104)\n+BCBD Compressed Size       0000002A (42)\n+BCC1 Uncompressed Size     00000037 (55)\n+BCC5 Filename Length       0035 (53)\n+BCC7 Extra Length          0000 (0)\n+BCC9 Comment Length        0000 (0)\n+BCCB Disk Start            0000 (0)\n+BCCD Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-BBE3 Ext File Attributes   81A40000 (2175008768)\n+BCCF Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-BBE7 Local Header Offset   0000A881 (43137)\n-BBEB Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+BCD3 Local Header Offset   0000A974 (43380)\n+BCD7 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xBBEB: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xBCD7: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-BC20 CENTRAL HEADER #41    02014B50 (33639248)\n-BC24 Created Zip Spec      14 (20) '2.0'\n-BC25 Created OS            03 (3) 'Unix'\n-BC26 Extract Zip Spec      14 (20) '2.0'\n-BC27 Extract OS            00 (0) 'MS-DOS'\n-BC28 General Purpose Flag  0800 (2048)\n+BD0C CENTRAL HEADER #41    02014B50 (33639248)\n+BD10 Created Zip Spec      14 (20) '2.0'\n+BD11 Created OS            03 (3) 'Unix'\n+BD12 Extract Zip Spec      14 (20) '2.0'\n+BD13 Extract OS            00 (0) 'MS-DOS'\n+BD14 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-BC2A Compression Method    0008 (8) 'Deflated'\n-BC2C Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-BC30 CRC                   45DB5347 (1172001607)\n-BC34 Compressed Size       00000448 (1096)\n-BC38 Uncompressed Size     00000FBC (4028)\n-BC3C Filename Length       0037 (55)\n-BC3E Extra Length          0000 (0)\n-BC40 Comment Length        0000 (0)\n-BC42 Disk Start            0000 (0)\n-BC44 Int File Attributes   0000 (0)\n+BD16 Compression Method    0008 (8) 'Deflated'\n+BD18 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+BD1C CRC                   C3B87E97 (3283648151)\n+BD20 Compressed Size       00000441 (1089)\n+BD24 Uncompressed Size     00000F4C (3916)\n+BD28 Filename Length       0037 (55)\n+BD2A Extra Length          0000 (0)\n+BD2C Comment Length        0000 (0)\n+BD2E Disk Start            0000 (0)\n+BD30 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-BC46 Ext File Attributes   81A40000 (2175008768)\n+BD32 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-BC4A Local Header Offset   0000A8FE (43262)\n-BC4E Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+BD36 Local Header Offset   0000A9F1 (43505)\n+BD3A Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xBC4E: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xBD3A: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-BC85 CENTRAL HEADER #42    02014B50 (33639248)\n-BC89 Created Zip Spec      14 (20) '2.0'\n-BC8A Created OS            03 (3) 'Unix'\n-BC8B Extract Zip Spec      14 (20) '2.0'\n-BC8C Extract OS            00 (0) 'MS-DOS'\n-BC8D General Purpose Flag  0800 (2048)\n+BD71 CENTRAL HEADER #42    02014B50 (33639248)\n+BD75 Created Zip Spec      14 (20) '2.0'\n+BD76 Created OS            03 (3) 'Unix'\n+BD77 Extract Zip Spec      14 (20) '2.0'\n+BD78 Extract OS            00 (0) 'MS-DOS'\n+BD79 General Purpose Flag  0800 (2048)\n      [Bits 1-2]            0 'Normal Compression'\n      [Bit 11]              1 'Language Encoding'\n-BC8F Compression Method    0008 (8) 'Deflated'\n-BC91 Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n-BC95 CRC                   BE4436A8 (3192141480)\n-BC99 Compressed Size       0000003E (62)\n-BC9D Uncompressed Size     00000046 (70)\n-BCA1 Filename Length       003E (62)\n-BCA3 Extra Length          0000 (0)\n-BCA5 Comment Length        0000 (0)\n-BCA7 Disk Start            0000 (0)\n-BCA9 Int File Attributes   0000 (0)\n+BD7B Compression Method    0008 (8) 'Deflated'\n+BD7D Modification Time     50814080 (1350647936) 'Wed Apr  1 08:04:00 2020'\n+BD81 CRC                   BE4436A8 (3192141480)\n+BD85 Compressed Size       0000003E (62)\n+BD89 Uncompressed Size     00000046 (70)\n+BD8D Filename Length       003E (62)\n+BD8F Extra Length          0000 (0)\n+BD91 Comment Length        0000 (0)\n+BD93 Disk Start            0000 (0)\n+BD95 Int File Attributes   0000 (0)\n      [Bit 0]               0 'Binary Data'\n-BCAB Ext File Attributes   81A40000 (2175008768)\n+BD97 Ext File Attributes   81A40000 (2175008768)\n      [Bits 16-24]          01A4 (420) 'Unix attrib: rw-r--r--'\n      [Bits 28-31]          08 (8) 'Regular File'\n-BCAF Local Header Offset   0000AD9B (44443)\n-BCB3 Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+BD9B Local Header Offset   0000AE87 (44679)\n+BD9F Filename              'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #\n-# WARNING: Offset 0xBCB3: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n+# WARNING: Offset 0xBD9F: Filename 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n #          Zero length filename\n #\n \n-BCF1 END CENTRAL HEADER    06054B50 (101010256)\n-BCF5 Number of this disk   0000 (0)\n-BCF7 Central Dir Disk no   0000 (0)\n-BCF9 Entries in this disk  002A (42)\n-BCFB Total Entries         002A (42)\n-BCFD Size of Central Dir   00000EBC (3772)\n-BD01 Offset to Central Dir 0000AE35 (44597)\n-BD05 Comment Length        0000 (0)\n+BDDD END CENTRAL HEADER    06054B50 (101010256)\n+BDE1 Number of this disk   0000 (0)\n+BDE3 Central Dir Disk no   0000 (0)\n+BDE5 Entries in this disk  002A (42)\n+BDE7 Total Entries         002A (42)\n+BDE9 Size of Central Dir   00000EBC (3772)\n+BDED Offset to Central Dir 0000AF21 (44833)\n+BDF1 Comment Length        0000 (0)\n #\n # Error Count: 14\n # Warning Count: 98\n #\n # Done\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,318 +1,318 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.common.bytecode.Wrapper;\n-import org.apache.dubbo.common.extension.ExtensionLoader;\n-import org.apache.dubbo.common.logger.Logger;\n-import org.apache.dubbo.common.logger.LoggerFactory;\n-import org.apache.dubbo.common.utils.ConcurrentHashSet;\n-import org.apache.dubbo.common.utils.StringUtils;\n-import org.apache.dubbo.remoting.Channel;\n-import org.apache.dubbo.remoting.Constants;\n-import org.apache.dubbo.remoting.RemotingException;\n-import org.apache.dubbo.rpc.Exporter;\n-import org.apache.dubbo.rpc.Invocation;\n-import org.apache.dubbo.rpc.Invoker;\n-import org.apache.dubbo.rpc.ProxyFactory;\n-import org.apache.dubbo.rpc.RpcInvocation;\n-import org.apache.dubbo.rpc.model.ApplicationModel;\n-import org.apache.dubbo.rpc.protocol.AsyncToSyncInvoker;\n-\n-import java.io.IOException;\n-import java.util.HashMap;\n-import java.util.Map;\n-import java.util.Set;\n-\n-import static org.apache.dubbo.common.constants.CommonConstants.CALLBACK_INSTANCES_LIMIT_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_CALLBACK_INSTANCES;\n-import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;\n-import static org.apache.dubbo.rpc.Constants.IS_SERVER_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_PROXY_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CHANNEL_CALLBACK_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.IS_CALLBACK_SERVICE;\n-\n-/**\n- * callback service helper\n- */\n-class CallbackServiceCodec {\n-    private static final Logger logger = LoggerFactory.getLogger(CallbackServiceCodec.class);\n-\n-    private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();\n-    private static final DubboProtocol PROTOCOL = DubboProtocol.getDubboProtocol();\n-    private static final byte CALLBACK_NONE = 0x0;\n-    private static final byte CALLBACK_CREATE = 0x1;\n-    private static final byte CALLBACK_DESTROY = 0x2;\n-    private static final String INV_ATT_CALLBACK_KEY = \"sys_callback_arg-\";\n-\n-    private static byte isCallBack(URL url, String protocolServiceKey, String methodName, int argIndex) {\n-        // parameter callback rule: method-name.parameter-index(starting from 0).callback\n-        byte isCallback = CALLBACK_NONE;\n-        if (url != null && url.hasServiceMethodParameter(protocolServiceKey, methodName)) {\n-            String callback = url.getServiceParameter(protocolServiceKey, methodName + \".\" + argIndex + \".callback\");\n-            if (callback != null) {\n-                if (\"true\".equalsIgnoreCase(callback)) {\n-                    isCallback = CALLBACK_CREATE;\n-                } else if (\"false\".equalsIgnoreCase(callback)) {\n-                    isCallback = CALLBACK_DESTROY;\n-                }\n-            }\n-        }\n-        return isCallback;\n-    }\n-\n-    /**\n-     * export or unexport callback service on client side\n-     *\n-     * @param channel\n-     * @param url\n-     * @param clazz\n-     * @param inst\n-     * @param export\n-     * @throws IOException\n-     */\n-    @SuppressWarnings({\"unchecked\", \"rawtypes\"})\n-    private static String exportOrUnexportCallbackService(Channel channel, URL url, Class clazz, Object inst, Boolean export) throws IOException {\n-        int instid = System.identityHashCode(inst);\n-\n-        Map<String, String> params = new HashMap<>(3);\n-        // no need to new client again\n-        params.put(IS_SERVER_KEY, Boolean.FALSE.toString());\n-        // mark it's a callback, for troubleshooting\n-        params.put(IS_CALLBACK_SERVICE, Boolean.TRUE.toString());\n-        String group = (url == null ? null : url.getParameter(GROUP_KEY));\n-        if (group != null && group.length() > 0) {\n-            params.put(GROUP_KEY, group);\n-        }\n-        // add method, for verifying against method, automatic fallback (see dubbo protocol)\n-        params.put(METHODS_KEY, StringUtils.join(Wrapper.getWrapper(clazz).getDeclaredMethodNames(), \",\"));\n-\n-        Map<String, String> tmpMap = new HashMap<>();\n-        if (url != null) {\n-            Map<String, String> parameters = url.getParameters();\n-            if (parameters != null && !parameters.isEmpty()) {\n-                tmpMap.putAll(parameters);\n-            }\n-        }\n-        tmpMap.putAll(params);\n-        \n-        tmpMap.remove(VERSION_KEY);// doesn't need to distinguish version for callback\n-        tmpMap.remove(Constants.BIND_PORT_KEY); //callback doesn't needs bind.port\n-        tmpMap.put(INTERFACE_KEY, clazz.getName());\n-        URL exportUrl = new URL(DubboProtocol.NAME, channel.getLocalAddress().getAddress().getHostAddress(), channel.getLocalAddress().getPort(), clazz.getName() + \".\" + instid, tmpMap);\n-\n-        // no need to generate multiple exporters for different channel in the same JVM, cache key cannot collide.\n-        String cacheKey = getClientSideCallbackServiceCacheKey(instid);\n-        String countKey = getClientSideCountKey(clazz.getName());\n-        if (export) {\n-            // one channel can have multiple callback instances, no need to re-export for different instance.\n-            if (!channel.hasAttribute(cacheKey)) {\n-                if (!isInstancesOverLimit(channel, url, clazz.getName(), instid, false)) {\n-                    ApplicationModel.getServiceRepository().registerService(clazz);\n-                    Invoker<?> invoker = PROXY_FACTORY.getInvoker(inst, clazz, exportUrl);\n-                    // should destroy resource?\n-                    Exporter<?> exporter = PROTOCOL.export(invoker);\n-                    // this is used for tracing if instid has published service or not.\n-                    channel.setAttribute(cacheKey, exporter);\n-                    logger.info(\"Export a callback service :\" + exportUrl + \", on \" + channel + \", url is: \" + url);\n-                    increaseInstanceCount(channel, countKey);\n-                }\n-            }\n-        } else {\n-            if (channel.hasAttribute(cacheKey)) {\n-                Exporter<?> exporter = (Exporter<?>) channel.getAttribute(cacheKey);\n-                exporter.unexport();\n-                channel.removeAttribute(cacheKey);\n-                decreaseInstanceCount(channel, countKey);\n-            }\n-        }\n-        return String.valueOf(instid);\n-    }\n-\n-    /**\n-     * refer or destroy callback service on server side\n-     *\n-     * @param url\n-     */\n-    @SuppressWarnings(\"unchecked\")\n-    private static Object referOrDestroyCallbackService(Channel channel, URL url, Class<?> clazz, Invocation inv, int instid, boolean isRefer) {\n-        Object proxy;\n-        String invokerCacheKey = getServerSideCallbackInvokerCacheKey(channel, clazz.getName(), instid);\n-        String proxyCacheKey = getServerSideCallbackServiceCacheKey(channel, clazz.getName(), instid);\n-        proxy = channel.getAttribute(proxyCacheKey);\n-        String countkey = getServerSideCountKey(channel, clazz.getName());\n-        if (isRefer) {\n-            if (proxy == null) {\n-                URL referurl = URL.valueOf(\"callback://\" + url.getAddress() + \"/\" + clazz.getName() + \"?\" + INTERFACE_KEY + \"=\" + clazz.getName());\n-                referurl = referurl.addParametersIfAbsent(url.getParameters()).removeParameter(METHODS_KEY);\n-                if (!isInstancesOverLimit(channel, referurl, clazz.getName(), instid, true)) {\n-                    ApplicationModel.getServiceRepository().registerService(clazz);\n-                    @SuppressWarnings(\"rawtypes\")\n-                    Invoker<?> invoker = new ChannelWrappedInvoker(clazz, channel, referurl, String.valueOf(instid));\n-                    proxy = PROXY_FACTORY.getProxy(new AsyncToSyncInvoker<>(invoker));\n-                    channel.setAttribute(proxyCacheKey, proxy);\n-                    channel.setAttribute(invokerCacheKey, invoker);\n-                    increaseInstanceCount(channel, countkey);\n-\n-                    //convert error fail fast .\n-                    //ignore concurrent problem.\n-                    Set<Invoker<?>> callbackInvokers = (Set<Invoker<?>>) channel.getAttribute(CHANNEL_CALLBACK_KEY);\n-                    if (callbackInvokers == null) {\n-                        callbackInvokers = new ConcurrentHashSet<>(1);\n-                        channel.setAttribute(CHANNEL_CALLBACK_KEY, callbackInvokers);\n-                    }\n-                    callbackInvokers.add(invoker);\n-                    logger.info(\"method \" + inv.getMethodName() + \" include a callback service :\" + invoker.getUrl() + \", a proxy :\" + invoker + \" has been created.\");\n-                }\n-            }\n-        } else {\n-            if (proxy != null) {\n-                Invoker<?> invoker = (Invoker<?>) channel.getAttribute(invokerCacheKey);\n-                try {\n-                    Set<Invoker<?>> callbackInvokers = (Set<Invoker<?>>) channel.getAttribute(CHANNEL_CALLBACK_KEY);\n-                    if (callbackInvokers != null) {\n-                        callbackInvokers.remove(invoker);\n-                    }\n-                    invoker.destroy();\n-                } catch (Exception e) {\n-                    logger.error(e.getMessage(), e);\n-                }\n-                // cancel refer, directly remove from the map\n-                channel.removeAttribute(proxyCacheKey);\n-                channel.removeAttribute(invokerCacheKey);\n-                decreaseInstanceCount(channel, countkey);\n-            }\n-        }\n-        return proxy;\n-    }\n-\n-    private static String getClientSideCallbackServiceCacheKey(int instid) {\n-        return CALLBACK_SERVICE_KEY + \".\" + instid;\n-    }\n-\n-    private static String getServerSideCallbackServiceCacheKey(Channel channel, String interfaceClass, int instid) {\n-        return CALLBACK_SERVICE_PROXY_KEY + \".\" + System.identityHashCode(channel) + \".\" + interfaceClass + \".\" + instid;\n-    }\n-\n-    private static String getServerSideCallbackInvokerCacheKey(Channel channel, String interfaceClass, int instid) {\n-        return getServerSideCallbackServiceCacheKey(channel, interfaceClass, instid) + \".\" + \"invoker\";\n-    }\n-\n-    private static String getClientSideCountKey(String interfaceClass) {\n-        return CALLBACK_SERVICE_KEY + \".\" + interfaceClass + \".COUNT\";\n-    }\n-\n-    private static String getServerSideCountKey(Channel channel, String interfaceClass) {\n-        return CALLBACK_SERVICE_PROXY_KEY + \".\" + System.identityHashCode(channel) + \".\" + interfaceClass + \".COUNT\";\n-    }\n-\n-    private static boolean isInstancesOverLimit(Channel channel, URL url, String interfaceClass, int instid, boolean isServer) {\n-        Integer count = (Integer) channel.getAttribute(isServer ? getServerSideCountKey(channel, interfaceClass) : getClientSideCountKey(interfaceClass));\n-        int limit = url.getParameter(CALLBACK_INSTANCES_LIMIT_KEY, DEFAULT_CALLBACK_INSTANCES);\n-        if (count != null && count >= limit) {\n-            //client side error\n-            throw new IllegalStateException(\"interface \" + interfaceClass + \" `s callback instances num exceed providers limit :\" + limit\n-                    + \" ,current num: \" + (count + 1) + \". The new callback service will not work !!! you can cancle the callback service which exported before. channel :\" + channel);\n-        } else {\n-            return false;\n-        }\n-    }\n-\n-    private static void increaseInstanceCount(Channel channel, String countkey) {\n-        try {\n-            //ignore concurrent problem?\n-            Integer count = (Integer) channel.getAttribute(countkey);\n-            if (count == null) {\n-                count = 1;\n-            } else {\n-                count++;\n-            }\n-            channel.setAttribute(countkey, count);\n-        } catch (Exception e) {\n-            logger.error(e.getMessage(), e);\n-        }\n-    }\n-\n-    private static void decreaseInstanceCount(Channel channel, String countkey) {\n-        try {\n-            Integer count = (Integer) channel.getAttribute(countkey);\n-            if (count == null || count <= 0) {\n-                return;\n-            } else {\n-                count--;\n-            }\n-            channel.setAttribute(countkey, count);\n-        } catch (Exception e) {\n-            logger.error(e.getMessage(), e);\n-        }\n-    }\n-\n-    public static Object encodeInvocationArgument(Channel channel, RpcInvocation inv, int paraIndex) throws IOException {\n-        // get URL directly\n-        URL url = inv.getInvoker() == null ? null : inv.getInvoker().getUrl();\n-        byte callbackStatus = isCallBack(url, inv.getProtocolServiceKey(), inv.getMethodName(), paraIndex);\n-        Object[] args = inv.getArguments();\n-        Class<?>[] pts = inv.getParameterTypes();\n-        switch (callbackStatus) {\n-            case CallbackServiceCodec.CALLBACK_CREATE:\n-                inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex, exportOrUnexportCallbackService(channel, url, pts[paraIndex], args[paraIndex], true));\n-                return null;\n-            case CallbackServiceCodec.CALLBACK_DESTROY:\n-                inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex, exportOrUnexportCallbackService(channel, url, pts[paraIndex], args[paraIndex], false));\n-                return null;\n-            default:\n-                return args[paraIndex];\n-        }\n-    }\n-\n-    public static Object decodeInvocationArgument(Channel channel, RpcInvocation inv, Class<?>[] pts, int paraIndex, Object inObject) throws IOException {\n-        // if it's a callback, create proxy on client side, callback interface on client side can be invoked through channel\n-        // need get URL from channel and env when decode\n-        URL url = null;\n-        try {\n-            url = DubboProtocol.getDubboProtocol().getInvoker(channel, inv).getUrl();\n-        } catch (RemotingException e) {\n-            if (logger.isInfoEnabled()) {\n-                logger.info(e.getMessage(), e);\n-            }\n-            return inObject;\n-        }\n-        byte callbackstatus = isCallBack(url, inv.getProtocolServiceKey(), inv.getMethodName(), paraIndex);\n-        switch (callbackstatus) {\n-            case CallbackServiceCodec.CALLBACK_CREATE:\n-                try {\n-                    return referOrDestroyCallbackService(channel, url, pts[paraIndex], inv, Integer.parseInt(inv.getAttachment(INV_ATT_CALLBACK_KEY + paraIndex)), true);\n-                } catch (Exception e) {\n-                    logger.error(e.getMessage(), e);\n-                    throw new IOException(StringUtils.toString(e));\n-                }\n-            case CallbackServiceCodec.CALLBACK_DESTROY:\n-                try {\n-                    return referOrDestroyCallbackService(channel, url, pts[paraIndex], inv, Integer.parseInt(inv.getAttachment(INV_ATT_CALLBACK_KEY + paraIndex)), false);\n-                } catch (Exception e) {\n-                    throw new IOException(StringUtils.toString(e));\n-                }\n-            default:\n-                return inObject;\n-        }\n-    }\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.common.bytecode.Wrapper;\r\n+import org.apache.dubbo.common.extension.ExtensionLoader;\r\n+import org.apache.dubbo.common.logger.Logger;\r\n+import org.apache.dubbo.common.logger.LoggerFactory;\r\n+import org.apache.dubbo.common.utils.ConcurrentHashSet;\r\n+import org.apache.dubbo.common.utils.StringUtils;\r\n+import org.apache.dubbo.remoting.Channel;\r\n+import org.apache.dubbo.remoting.Constants;\r\n+import org.apache.dubbo.remoting.RemotingException;\r\n+import org.apache.dubbo.rpc.Exporter;\r\n+import org.apache.dubbo.rpc.Invocation;\r\n+import org.apache.dubbo.rpc.Invoker;\r\n+import org.apache.dubbo.rpc.ProxyFactory;\r\n+import org.apache.dubbo.rpc.RpcInvocation;\r\n+import org.apache.dubbo.rpc.model.ApplicationModel;\r\n+import org.apache.dubbo.rpc.protocol.AsyncToSyncInvoker;\r\n+\r\n+import java.io.IOException;\r\n+import java.util.HashMap;\r\n+import java.util.Map;\r\n+import java.util.Set;\r\n+\r\n+import static org.apache.dubbo.common.constants.CommonConstants.CALLBACK_INSTANCES_LIMIT_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_CALLBACK_INSTANCES;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;\r\n+import static org.apache.dubbo.rpc.Constants.IS_SERVER_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_PROXY_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CHANNEL_CALLBACK_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.IS_CALLBACK_SERVICE;\r\n+\r\n+/**\r\n+ * callback service helper\r\n+ */\r\n+class CallbackServiceCodec {\r\n+    private static final Logger logger = LoggerFactory.getLogger(CallbackServiceCodec.class);\r\n+\r\n+    private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();\r\n+    private static final DubboProtocol PROTOCOL = DubboProtocol.getDubboProtocol();\r\n+    private static final byte CALLBACK_NONE = 0x0;\r\n+    private static final byte CALLBACK_CREATE = 0x1;\r\n+    private static final byte CALLBACK_DESTROY = 0x2;\r\n+    private static final String INV_ATT_CALLBACK_KEY = \"sys_callback_arg-\";\r\n+\r\n+    private static byte isCallBack(URL url, String protocolServiceKey, String methodName, int argIndex) {\r\n+        // parameter callback rule: method-name.parameter-index(starting from 0).callback\r\n+        byte isCallback = CALLBACK_NONE;\r\n+        if (url != null && url.hasServiceMethodParameter(protocolServiceKey, methodName)) {\r\n+            String callback = url.getServiceParameter(protocolServiceKey, methodName + \".\" + argIndex + \".callback\");\r\n+            if (callback != null) {\r\n+                if (\"true\".equalsIgnoreCase(callback)) {\r\n+                    isCallback = CALLBACK_CREATE;\r\n+                } else if (\"false\".equalsIgnoreCase(callback)) {\r\n+                    isCallback = CALLBACK_DESTROY;\r\n+                }\r\n+            }\r\n+        }\r\n+        return isCallback;\r\n+    }\r\n+\r\n+    /**\r\n+     * export or unexport callback service on client side\r\n+     *\r\n+     * @param channel\r\n+     * @param url\r\n+     * @param clazz\r\n+     * @param inst\r\n+     * @param export\r\n+     * @throws IOException\r\n+     */\r\n+    @SuppressWarnings({\"unchecked\", \"rawtypes\"})\r\n+    private static String exportOrUnexportCallbackService(Channel channel, URL url, Class clazz, Object inst, Boolean export) throws IOException {\r\n+        int instid = System.identityHashCode(inst);\r\n+\r\n+        Map<String, String> params = new HashMap<>(3);\r\n+        // no need to new client again\r\n+        params.put(IS_SERVER_KEY, Boolean.FALSE.toString());\r\n+        // mark it's a callback, for troubleshooting\r\n+        params.put(IS_CALLBACK_SERVICE, Boolean.TRUE.toString());\r\n+        String group = (url == null ? null : url.getParameter(GROUP_KEY));\r\n+        if (group != null && group.length() > 0) {\r\n+            params.put(GROUP_KEY, group);\r\n+        }\r\n+        // add method, for verifying against method, automatic fallback (see dubbo protocol)\r\n+        params.put(METHODS_KEY, StringUtils.join(Wrapper.getWrapper(clazz).getDeclaredMethodNames(), \",\"));\r\n+\r\n+        Map<String, String> tmpMap = new HashMap<>();\r\n+        if (url != null) {\r\n+            Map<String, String> parameters = url.getParameters();\r\n+            if (parameters != null && !parameters.isEmpty()) {\r\n+                tmpMap.putAll(parameters);\r\n+            }\r\n+        }\r\n+        tmpMap.putAll(params);\r\n+        \r\n+        tmpMap.remove(VERSION_KEY);// doesn't need to distinguish version for callback\r\n+        tmpMap.remove(Constants.BIND_PORT_KEY); //callback doesn't needs bind.port\r\n+        tmpMap.put(INTERFACE_KEY, clazz.getName());\r\n+        URL exportUrl = new URL(DubboProtocol.NAME, channel.getLocalAddress().getAddress().getHostAddress(), channel.getLocalAddress().getPort(), clazz.getName() + \".\" + instid, tmpMap);\r\n+\r\n+        // no need to generate multiple exporters for different channel in the same JVM, cache key cannot collide.\r\n+        String cacheKey = getClientSideCallbackServiceCacheKey(instid);\r\n+        String countKey = getClientSideCountKey(clazz.getName());\r\n+        if (export) {\r\n+            // one channel can have multiple callback instances, no need to re-export for different instance.\r\n+            if (!channel.hasAttribute(cacheKey)) {\r\n+                if (!isInstancesOverLimit(channel, url, clazz.getName(), instid, false)) {\r\n+                    ApplicationModel.getServiceRepository().registerService(clazz);\r\n+                    Invoker<?> invoker = PROXY_FACTORY.getInvoker(inst, clazz, exportUrl);\r\n+                    // should destroy resource?\r\n+                    Exporter<?> exporter = PROTOCOL.export(invoker);\r\n+                    // this is used for tracing if instid has published service or not.\r\n+                    channel.setAttribute(cacheKey, exporter);\r\n+                    logger.info(\"Export a callback service :\" + exportUrl + \", on \" + channel + \", url is: \" + url);\r\n+                    increaseInstanceCount(channel, countKey);\r\n+                }\r\n+            }\r\n+        } else {\r\n+            if (channel.hasAttribute(cacheKey)) {\r\n+                Exporter<?> exporter = (Exporter<?>) channel.getAttribute(cacheKey);\r\n+                exporter.unexport();\r\n+                channel.removeAttribute(cacheKey);\r\n+                decreaseInstanceCount(channel, countKey);\r\n+            }\r\n+        }\r\n+        return String.valueOf(instid);\r\n+    }\r\n+\r\n+    /**\r\n+     * refer or destroy callback service on server side\r\n+     *\r\n+     * @param url\r\n+     */\r\n+    @SuppressWarnings(\"unchecked\")\r\n+    private static Object referOrDestroyCallbackService(Channel channel, URL url, Class<?> clazz, Invocation inv, int instid, boolean isRefer) {\r\n+        Object proxy;\r\n+        String invokerCacheKey = getServerSideCallbackInvokerCacheKey(channel, clazz.getName(), instid);\r\n+        String proxyCacheKey = getServerSideCallbackServiceCacheKey(channel, clazz.getName(), instid);\r\n+        proxy = channel.getAttribute(proxyCacheKey);\r\n+        String countkey = getServerSideCountKey(channel, clazz.getName());\r\n+        if (isRefer) {\r\n+            if (proxy == null) {\r\n+                URL referurl = URL.valueOf(\"callback://\" + url.getAddress() + \"/\" + clazz.getName() + \"?\" + INTERFACE_KEY + \"=\" + clazz.getName());\r\n+                referurl = referurl.addParametersIfAbsent(url.getParameters()).removeParameter(METHODS_KEY);\r\n+                if (!isInstancesOverLimit(channel, referurl, clazz.getName(), instid, true)) {\r\n+                    ApplicationModel.getServiceRepository().registerService(clazz);\r\n+                    @SuppressWarnings(\"rawtypes\")\r\n+                    Invoker<?> invoker = new ChannelWrappedInvoker(clazz, channel, referurl, String.valueOf(instid));\r\n+                    proxy = PROXY_FACTORY.getProxy(new AsyncToSyncInvoker<>(invoker));\r\n+                    channel.setAttribute(proxyCacheKey, proxy);\r\n+                    channel.setAttribute(invokerCacheKey, invoker);\r\n+                    increaseInstanceCount(channel, countkey);\r\n+\r\n+                    //convert error fail fast .\r\n+                    //ignore concurrent problem.\r\n+                    Set<Invoker<?>> callbackInvokers = (Set<Invoker<?>>) channel.getAttribute(CHANNEL_CALLBACK_KEY);\r\n+                    if (callbackInvokers == null) {\r\n+                        callbackInvokers = new ConcurrentHashSet<>(1);\r\n+                        channel.setAttribute(CHANNEL_CALLBACK_KEY, callbackInvokers);\r\n+                    }\r\n+                    callbackInvokers.add(invoker);\r\n+                    logger.info(\"method \" + inv.getMethodName() + \" include a callback service :\" + invoker.getUrl() + \", a proxy :\" + invoker + \" has been created.\");\r\n+                }\r\n+            }\r\n+        } else {\r\n+            if (proxy != null) {\r\n+                Invoker<?> invoker = (Invoker<?>) channel.getAttribute(invokerCacheKey);\r\n+                try {\r\n+                    Set<Invoker<?>> callbackInvokers = (Set<Invoker<?>>) channel.getAttribute(CHANNEL_CALLBACK_KEY);\r\n+                    if (callbackInvokers != null) {\r\n+                        callbackInvokers.remove(invoker);\r\n+                    }\r\n+                    invoker.destroy();\r\n+                } catch (Exception e) {\r\n+                    logger.error(e.getMessage(), e);\r\n+                }\r\n+                // cancel refer, directly remove from the map\r\n+                channel.removeAttribute(proxyCacheKey);\r\n+                channel.removeAttribute(invokerCacheKey);\r\n+                decreaseInstanceCount(channel, countkey);\r\n+            }\r\n+        }\r\n+        return proxy;\r\n+    }\r\n+\r\n+    private static String getClientSideCallbackServiceCacheKey(int instid) {\r\n+        return CALLBACK_SERVICE_KEY + \".\" + instid;\r\n+    }\r\n+\r\n+    private static String getServerSideCallbackServiceCacheKey(Channel channel, String interfaceClass, int instid) {\r\n+        return CALLBACK_SERVICE_PROXY_KEY + \".\" + System.identityHashCode(channel) + \".\" + interfaceClass + \".\" + instid;\r\n+    }\r\n+\r\n+    private static String getServerSideCallbackInvokerCacheKey(Channel channel, String interfaceClass, int instid) {\r\n+        return getServerSideCallbackServiceCacheKey(channel, interfaceClass, instid) + \".\" + \"invoker\";\r\n+    }\r\n+\r\n+    private static String getClientSideCountKey(String interfaceClass) {\r\n+        return CALLBACK_SERVICE_KEY + \".\" + interfaceClass + \".COUNT\";\r\n+    }\r\n+\r\n+    private static String getServerSideCountKey(Channel channel, String interfaceClass) {\r\n+        return CALLBACK_SERVICE_PROXY_KEY + \".\" + System.identityHashCode(channel) + \".\" + interfaceClass + \".COUNT\";\r\n+    }\r\n+\r\n+    private static boolean isInstancesOverLimit(Channel channel, URL url, String interfaceClass, int instid, boolean isServer) {\r\n+        Integer count = (Integer) channel.getAttribute(isServer ? getServerSideCountKey(channel, interfaceClass) : getClientSideCountKey(interfaceClass));\r\n+        int limit = url.getParameter(CALLBACK_INSTANCES_LIMIT_KEY, DEFAULT_CALLBACK_INSTANCES);\r\n+        if (count != null && count >= limit) {\r\n+            //client side error\r\n+            throw new IllegalStateException(\"interface \" + interfaceClass + \" `s callback instances num exceed providers limit :\" + limit\r\n+                    + \" ,current num: \" + (count + 1) + \". The new callback service will not work !!! you can cancle the callback service which exported before. channel :\" + channel);\r\n+        } else {\r\n+            return false;\r\n+        }\r\n+    }\r\n+\r\n+    private static void increaseInstanceCount(Channel channel, String countkey) {\r\n+        try {\r\n+            //ignore concurrent problem?\r\n+            Integer count = (Integer) channel.getAttribute(countkey);\r\n+            if (count == null) {\r\n+                count = 1;\r\n+            } else {\r\n+                count++;\r\n+            }\r\n+            channel.setAttribute(countkey, count);\r\n+        } catch (Exception e) {\r\n+            logger.error(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    private static void decreaseInstanceCount(Channel channel, String countkey) {\r\n+        try {\r\n+            Integer count = (Integer) channel.getAttribute(countkey);\r\n+            if (count == null || count <= 0) {\r\n+                return;\r\n+            } else {\r\n+                count--;\r\n+            }\r\n+            channel.setAttribute(countkey, count);\r\n+        } catch (Exception e) {\r\n+            logger.error(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    public static Object encodeInvocationArgument(Channel channel, RpcInvocation inv, int paraIndex) throws IOException {\r\n+        // get URL directly\r\n+        URL url = inv.getInvoker() == null ? null : inv.getInvoker().getUrl();\r\n+        byte callbackStatus = isCallBack(url, inv.getProtocolServiceKey(), inv.getMethodName(), paraIndex);\r\n+        Object[] args = inv.getArguments();\r\n+        Class<?>[] pts = inv.getParameterTypes();\r\n+        switch (callbackStatus) {\r\n+            case CallbackServiceCodec.CALLBACK_CREATE:\r\n+                inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex, exportOrUnexportCallbackService(channel, url, pts[paraIndex], args[paraIndex], true));\r\n+                return null;\r\n+            case CallbackServiceCodec.CALLBACK_DESTROY:\r\n+                inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex, exportOrUnexportCallbackService(channel, url, pts[paraIndex], args[paraIndex], false));\r\n+                return null;\r\n+            default:\r\n+                return args[paraIndex];\r\n+        }\r\n+    }\r\n+\r\n+    public static Object decodeInvocationArgument(Channel channel, RpcInvocation inv, Class<?>[] pts, int paraIndex, Object inObject) throws IOException {\r\n+        // if it's a callback, create proxy on client side, callback interface on client side can be invoked through channel\r\n+        // need get URL from channel and env when decode\r\n+        URL url = null;\r\n+        try {\r\n+            url = DubboProtocol.getDubboProtocol().getInvoker(channel, inv).getUrl();\r\n+        } catch (RemotingException e) {\r\n+            if (logger.isInfoEnabled()) {\r\n+                logger.info(e.getMessage(), e);\r\n+            }\r\n+            return inObject;\r\n+        }\r\n+        byte callbackstatus = isCallBack(url, inv.getProtocolServiceKey(), inv.getMethodName(), paraIndex);\r\n+        switch (callbackstatus) {\r\n+            case CallbackServiceCodec.CALLBACK_CREATE:\r\n+                try {\r\n+                    return referOrDestroyCallbackService(channel, url, pts[paraIndex], inv, Integer.parseInt(inv.getAttachment(INV_ATT_CALLBACK_KEY + paraIndex)), true);\r\n+                } catch (Exception e) {\r\n+                    logger.error(e.getMessage(), e);\r\n+                    throw new IOException(StringUtils.toString(e));\r\n+                }\r\n+            case CallbackServiceCodec.CALLBACK_DESTROY:\r\n+                try {\r\n+                    return referOrDestroyCallbackService(channel, url, pts[paraIndex], inv, Integer.parseInt(inv.getAttachment(INV_ATT_CALLBACK_KEY + paraIndex)), false);\r\n+                } catch (Exception e) {\r\n+                    throw new IOException(StringUtils.toString(e));\r\n+                }\r\n+            default:\r\n+                return inObject;\r\n+        }\r\n+    }\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,183 +1,183 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.remoting.Channel;\n-import org.apache.dubbo.remoting.ChannelHandler;\n-import org.apache.dubbo.remoting.RemotingException;\n-import org.apache.dubbo.remoting.TimeoutException;\n-import org.apache.dubbo.remoting.exchange.ExchangeClient;\n-import org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeClient;\n-import org.apache.dubbo.remoting.transport.ClientDelegate;\n-import org.apache.dubbo.rpc.AppResponse;\n-import org.apache.dubbo.rpc.AsyncRpcResult;\n-import org.apache.dubbo.rpc.Invocation;\n-import org.apache.dubbo.rpc.Result;\n-import org.apache.dubbo.rpc.RpcException;\n-import org.apache.dubbo.rpc.RpcInvocation;\n-import org.apache.dubbo.rpc.protocol.AbstractInvoker;\n-import org.apache.dubbo.rpc.support.RpcUtils;\n-\n-import java.net.InetSocketAddress;\n-import java.util.concurrent.CompletableFuture;\n-\n-import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;\n-import static org.apache.dubbo.remoting.Constants.SENT_KEY;\n-import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;\n-\n-/**\n- * Server push uses this Invoker to continuously push data to client.\n- * Wrap the existing invoker on the channel.\n- */\n-class ChannelWrappedInvoker<T> extends AbstractInvoker<T> {\n-\n-    private final Channel channel;\n-    private final String serviceKey;\n-    private final ExchangeClient currentClient;\n-\n-    ChannelWrappedInvoker(Class<T> serviceType, Channel channel, URL url, String serviceKey) {\n-        super(serviceType, url, new String[]{GROUP_KEY, TOKEN_KEY});\n-        this.channel = channel;\n-        this.serviceKey = serviceKey;\n-        this.currentClient = new HeaderExchangeClient(new ChannelWrapper(this.channel), false);\n-    }\n-\n-    @Override\n-    protected Result doInvoke(Invocation invocation) throws Throwable {\n-        RpcInvocation inv = (RpcInvocation) invocation;\n-        // use interface's name as service path to export if it's not found on client side\n-        inv.setAttachment(PATH_KEY, getInterface().getName());\n-        inv.setAttachment(CALLBACK_SERVICE_KEY, serviceKey);\n-\n-        try {\n-            if (RpcUtils.isOneway(getUrl(), inv)) { // may have concurrency issue\n-                currentClient.send(inv, getUrl().getMethodParameter(invocation.getMethodName(), SENT_KEY, false));\n-                return AsyncRpcResult.newDefaultAsyncResult(invocation);\n-            } else {\n-                CompletableFuture<AppResponse> appResponseFuture = currentClient.request(inv).thenApply(obj -> (AppResponse) obj);\n-                return new AsyncRpcResult(appResponseFuture, inv);\n-            }\n-        } catch (RpcException e) {\n-            throw e;\n-        } catch (TimeoutException e) {\n-            throw new RpcException(RpcException.TIMEOUT_EXCEPTION, e.getMessage(), e);\n-        } catch (RemotingException e) {\n-            throw new RpcException(RpcException.NETWORK_EXCEPTION, e.getMessage(), e);\n-        } catch (Throwable e) { // here is non-biz exception, wrap it.\n-            throw new RpcException(e.getMessage(), e);\n-        }\n-    }\n-\n-    @Override\n-    public void destroy() {\n-//        super.destroy();\n-//        try {\n-//            channel.close();\n-//        } catch (Throwable t) {\n-//            logger.warn(t.getMessage(), t);\n-//        }\n-    }\n-\n-    public static class ChannelWrapper extends ClientDelegate {\n-\n-        private final Channel channel;\n-        private final URL url;\n-\n-        ChannelWrapper(Channel channel) {\n-            this.channel = channel;\n-            this.url = channel.getUrl().addParameter(\"codec\", DubboCodec.NAME);\n-        }\n-\n-        @Override\n-        public URL getUrl() {\n-            return url;\n-        }\n-\n-        @Override\n-        public ChannelHandler getChannelHandler() {\n-            return channel.getChannelHandler();\n-        }\n-\n-        @Override\n-        public InetSocketAddress getLocalAddress() {\n-            return channel.getLocalAddress();\n-        }\n-\n-        @Override\n-        public void close() {\n-            channel.close();\n-        }\n-\n-        @Override\n-        public boolean isClosed() {\n-            return channel == null || channel.isClosed();\n-        }\n-\n-        @Override\n-        public void reset(URL url) {\n-            throw new RpcException(\"ChannelInvoker can not reset.\");\n-        }\n-\n-        @Override\n-        public InetSocketAddress getRemoteAddress() {\n-            return channel.getLocalAddress();\n-        }\n-\n-        @Override\n-        public boolean isConnected() {\n-            return channel != null && channel.isConnected();\n-        }\n-\n-        @Override\n-        public boolean hasAttribute(String key) {\n-            return channel.hasAttribute(key);\n-        }\n-\n-        @Override\n-        public Object getAttribute(String key) {\n-            return channel.getAttribute(key);\n-        }\n-\n-        @Override\n-        public void setAttribute(String key, Object value) {\n-            channel.setAttribute(key, value);\n-        }\n-\n-        @Override\n-        public void removeAttribute(String key) {\n-            channel.removeAttribute(key);\n-        }\n-\n-        @Override\n-        public void reconnect() throws RemotingException {\n-\n-        }\n-\n-        @Override\n-        public void send(Object message) throws RemotingException {\n-            channel.send(message);\n-        }\n-\n-        @Override\n-        public void send(Object message, boolean sent) throws RemotingException {\n-            channel.send(message, sent);\n-        }\n-    }\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.remoting.Channel;\r\n+import org.apache.dubbo.remoting.ChannelHandler;\r\n+import org.apache.dubbo.remoting.RemotingException;\r\n+import org.apache.dubbo.remoting.TimeoutException;\r\n+import org.apache.dubbo.remoting.exchange.ExchangeClient;\r\n+import org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeClient;\r\n+import org.apache.dubbo.remoting.transport.ClientDelegate;\r\n+import org.apache.dubbo.rpc.AppResponse;\r\n+import org.apache.dubbo.rpc.AsyncRpcResult;\r\n+import org.apache.dubbo.rpc.Invocation;\r\n+import org.apache.dubbo.rpc.Result;\r\n+import org.apache.dubbo.rpc.RpcException;\r\n+import org.apache.dubbo.rpc.RpcInvocation;\r\n+import org.apache.dubbo.rpc.protocol.AbstractInvoker;\r\n+import org.apache.dubbo.rpc.support.RpcUtils;\r\n+\r\n+import java.net.InetSocketAddress;\r\n+import java.util.concurrent.CompletableFuture;\r\n+\r\n+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;\r\n+import static org.apache.dubbo.remoting.Constants.SENT_KEY;\r\n+import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;\r\n+\r\n+/**\r\n+ * Server push uses this Invoker to continuously push data to client.\r\n+ * Wrap the existing invoker on the channel.\r\n+ */\r\n+class ChannelWrappedInvoker<T> extends AbstractInvoker<T> {\r\n+\r\n+    private final Channel channel;\r\n+    private final String serviceKey;\r\n+    private final ExchangeClient currentClient;\r\n+\r\n+    ChannelWrappedInvoker(Class<T> serviceType, Channel channel, URL url, String serviceKey) {\r\n+        super(serviceType, url, new String[]{GROUP_KEY, TOKEN_KEY});\r\n+        this.channel = channel;\r\n+        this.serviceKey = serviceKey;\r\n+        this.currentClient = new HeaderExchangeClient(new ChannelWrapper(this.channel), false);\r\n+    }\r\n+\r\n+    @Override\r\n+    protected Result doInvoke(Invocation invocation) throws Throwable {\r\n+        RpcInvocation inv = (RpcInvocation) invocation;\r\n+        // use interface's name as service path to export if it's not found on client side\r\n+        inv.setAttachment(PATH_KEY, getInterface().getName());\r\n+        inv.setAttachment(CALLBACK_SERVICE_KEY, serviceKey);\r\n+\r\n+        try {\r\n+            if (RpcUtils.isOneway(getUrl(), inv)) { // may have concurrency issue\r\n+                currentClient.send(inv, getUrl().getMethodParameter(invocation.getMethodName(), SENT_KEY, false));\r\n+                return AsyncRpcResult.newDefaultAsyncResult(invocation);\r\n+            } else {\r\n+                CompletableFuture<AppResponse> appResponseFuture = currentClient.request(inv).thenApply(obj -> (AppResponse) obj);\r\n+                return new AsyncRpcResult(appResponseFuture, inv);\r\n+            }\r\n+        } catch (RpcException e) {\r\n+            throw e;\r\n+        } catch (TimeoutException e) {\r\n+            throw new RpcException(RpcException.TIMEOUT_EXCEPTION, e.getMessage(), e);\r\n+        } catch (RemotingException e) {\r\n+            throw new RpcException(RpcException.NETWORK_EXCEPTION, e.getMessage(), e);\r\n+        } catch (Throwable e) { // here is non-biz exception, wrap it.\r\n+            throw new RpcException(e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public void destroy() {\r\n+//        super.destroy();\r\n+//        try {\r\n+//            channel.close();\r\n+//        } catch (Throwable t) {\r\n+//            logger.warn(t.getMessage(), t);\r\n+//        }\r\n+    }\r\n+\r\n+    public static class ChannelWrapper extends ClientDelegate {\r\n+\r\n+        private final Channel channel;\r\n+        private final URL url;\r\n+\r\n+        ChannelWrapper(Channel channel) {\r\n+            this.channel = channel;\r\n+            this.url = channel.getUrl().addParameter(\"codec\", DubboCodec.NAME);\r\n+        }\r\n+\r\n+        @Override\r\n+        public URL getUrl() {\r\n+            return url;\r\n+        }\r\n+\r\n+        @Override\r\n+        public ChannelHandler getChannelHandler() {\r\n+            return channel.getChannelHandler();\r\n+        }\r\n+\r\n+        @Override\r\n+        public InetSocketAddress getLocalAddress() {\r\n+            return channel.getLocalAddress();\r\n+        }\r\n+\r\n+        @Override\r\n+        public void close() {\r\n+            channel.close();\r\n+        }\r\n+\r\n+        @Override\r\n+        public boolean isClosed() {\r\n+            return channel == null || channel.isClosed();\r\n+        }\r\n+\r\n+        @Override\r\n+        public void reset(URL url) {\r\n+            throw new RpcException(\"ChannelInvoker can not reset.\");\r\n+        }\r\n+\r\n+        @Override\r\n+        public InetSocketAddress getRemoteAddress() {\r\n+            return channel.getLocalAddress();\r\n+        }\r\n+\r\n+        @Override\r\n+        public boolean isConnected() {\r\n+            return channel != null && channel.isConnected();\r\n+        }\r\n+\r\n+        @Override\r\n+        public boolean hasAttribute(String key) {\r\n+            return channel.hasAttribute(key);\r\n+        }\r\n+\r\n+        @Override\r\n+        public Object getAttribute(String key) {\r\n+            return channel.getAttribute(key);\r\n+        }\r\n+\r\n+        @Override\r\n+        public void setAttribute(String key, Object value) {\r\n+            channel.setAttribute(key, value);\r\n+        }\r\n+\r\n+        @Override\r\n+        public void removeAttribute(String key) {\r\n+            channel.removeAttribute(key);\r\n+        }\r\n+\r\n+        @Override\r\n+        public void reconnect() throws RemotingException {\r\n+\r\n+        }\r\n+\r\n+        @Override\r\n+        public void send(Object message) throws RemotingException {\r\n+            channel.send(message);\r\n+        }\r\n+\r\n+        @Override\r\n+        public void send(Object message, boolean sent) throws RemotingException {\r\n+            channel.send(message, sent);\r\n+        }\r\n+    }\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/Constants.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/Constants.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,71 +1,71 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-/**\n- *\n- */\n-public interface Constants {\n-\n-    String SHARE_CONNECTIONS_KEY = \"shareconnections\";\n-\n-    /**\n-     * By default, a consumer JVM instance and a provider JVM instance share a long TCP connection (except when connections are set),\n-     * which can set the number of long TCP connections shared to avoid the bottleneck of sharing a single long TCP connection.\n-     */\n-    String DEFAULT_SHARE_CONNECTIONS = \"1\";\n-\n-    String DECODE_IN_IO_THREAD_KEY = \"decode.in.io\";\n-\n-    boolean DEFAULT_DECODE_IN_IO_THREAD = false;\n-\n-    /**\n-     * callback inst id\n-     */\n-    String CALLBACK_SERVICE_KEY = \"callback.service.instid\";\n-\n-    String CALLBACK_SERVICE_PROXY_KEY = \"callback.service.proxy\";\n-\n-    String IS_CALLBACK_SERVICE = \"is_callback_service\";\n-\n-    /**\n-     * Invokers in channel's callback\n-     */\n-    String CHANNEL_CALLBACK_KEY = \"channel.callback.invokers.key\";\n-\n-    /**\n-     * The initial state for lazy connection\n-     */\n-    String LAZY_CONNECT_INITIAL_STATE_KEY = \"connect.lazy.initial.state\";\n-\n-    /**\n-     * The default value of lazy connection's initial state: true\n-     *\n-     * @see #LAZY_CONNECT_INITIAL_STATE_KEY\n-     */\n-    boolean DEFAULT_LAZY_CONNECT_INITIAL_STATE = true;\n-\n-    String OPTIMIZER_KEY = \"optimizer\";\n-\n-    String ON_CONNECT_KEY = \"onconnect\";\n-\n-    String ON_DISCONNECT_KEY = \"ondisconnect\";\n-\n-    String ASYNC_METHOD_INFO = \"async-method-info\";\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+/**\r\n+ *\r\n+ */\r\n+public interface Constants {\r\n+\r\n+    String SHARE_CONNECTIONS_KEY = \"shareconnections\";\r\n+\r\n+    /**\r\n+     * By default, a consumer JVM instance and a provider JVM instance share a long TCP connection (except when connections are set),\r\n+     * which can set the number of long TCP connections shared to avoid the bottleneck of sharing a single long TCP connection.\r\n+     */\r\n+    String DEFAULT_SHARE_CONNECTIONS = \"1\";\r\n+\r\n+    String DECODE_IN_IO_THREAD_KEY = \"decode.in.io\";\r\n+\r\n+    boolean DEFAULT_DECODE_IN_IO_THREAD = false;\r\n+\r\n+    /**\r\n+     * callback inst id\r\n+     */\r\n+    String CALLBACK_SERVICE_KEY = \"callback.service.instid\";\r\n+\r\n+    String CALLBACK_SERVICE_PROXY_KEY = \"callback.service.proxy\";\r\n+\r\n+    String IS_CALLBACK_SERVICE = \"is_callback_service\";\r\n+\r\n+    /**\r\n+     * Invokers in channel's callback\r\n+     */\r\n+    String CHANNEL_CALLBACK_KEY = \"channel.callback.invokers.key\";\r\n+\r\n+    /**\r\n+     * The initial state for lazy connection\r\n+     */\r\n+    String LAZY_CONNECT_INITIAL_STATE_KEY = \"connect.lazy.initial.state\";\r\n+\r\n+    /**\r\n+     * The default value of lazy connection's initial state: true\r\n+     *\r\n+     * @see #LAZY_CONNECT_INITIAL_STATE_KEY\r\n+     */\r\n+    boolean DEFAULT_LAZY_CONNECT_INITIAL_STATE = true;\r\n+\r\n+    String OPTIMIZER_KEY = \"optimizer\";\r\n+\r\n+    String ON_CONNECT_KEY = \"onconnect\";\r\n+\r\n+    String ON_DISCONNECT_KEY = \"ondisconnect\";\r\n+\r\n+    String ASYNC_METHOD_INFO = \"async-method-info\";\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,195 +1,195 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-\n-import org.apache.dubbo.common.config.ConfigurationUtils;\n-import org.apache.dubbo.common.logger.Logger;\n-import org.apache.dubbo.common.logger.LoggerFactory;\n-import org.apache.dubbo.common.serialize.Cleanable;\n-import org.apache.dubbo.common.serialize.ObjectInput;\n-import org.apache.dubbo.common.utils.Assert;\n-import org.apache.dubbo.common.utils.ReflectUtils;\n-import org.apache.dubbo.common.utils.StringUtils;\n-import org.apache.dubbo.remoting.Channel;\n-import org.apache.dubbo.remoting.Codec;\n-import org.apache.dubbo.remoting.Decodeable;\n-import org.apache.dubbo.remoting.exchange.Request;\n-import org.apache.dubbo.remoting.transport.CodecSupport;\n-import org.apache.dubbo.rpc.RpcInvocation;\n-import org.apache.dubbo.rpc.model.ApplicationModel;\n-import org.apache.dubbo.rpc.model.MethodDescriptor;\n-import org.apache.dubbo.rpc.model.ServiceDescriptor;\n-import org.apache.dubbo.rpc.model.ServiceRepository;\n-import org.apache.dubbo.rpc.support.RpcUtils;\n-\n-import java.io.IOException;\n-import java.io.InputStream;\n-import java.io.OutputStream;\n-import java.util.HashMap;\n-import java.util.Map;\n-\n-import static org.apache.dubbo.common.URL.buildKey;\n-import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;\n-import static org.apache.dubbo.rpc.Constants.SERIALIZATION_ID_KEY;\n-import static org.apache.dubbo.rpc.Constants.SERIALIZATION_SECURITY_CHECK_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.CallbackServiceCodec.decodeInvocationArgument;\n-\n-public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Decodeable {\n-\n-    private static final Logger log = LoggerFactory.getLogger(DecodeableRpcInvocation.class);\n-\n-    private Channel channel;\n-\n-    private byte serializationType;\n-\n-    private InputStream inputStream;\n-\n-    private Request request;\n-\n-    private volatile boolean hasDecoded;\n-\n-    public DecodeableRpcInvocation(Channel channel, Request request, InputStream is, byte id) {\n-        Assert.notNull(channel, \"channel == null\");\n-        Assert.notNull(request, \"request == null\");\n-        Assert.notNull(is, \"inputStream == null\");\n-        this.channel = channel;\n-        this.request = request;\n-        this.inputStream = is;\n-        this.serializationType = id;\n-    }\n-\n-    @Override\n-    public void decode() throws Exception {\n-        if (!hasDecoded && channel != null && inputStream != null) {\n-            try {\n-                decode(channel, inputStream);\n-            } catch (Throwable e) {\n-                if (log.isWarnEnabled()) {\n-                    log.warn(\"Decode rpc invocation failed: \" + e.getMessage(), e);\n-                }\n-                request.setBroken(true);\n-                request.setData(e);\n-            } finally {\n-                hasDecoded = true;\n-            }\n-        }\n-    }\n-\n-    @Override\n-    public void encode(Channel channel, OutputStream output, Object message) throws IOException {\n-        throw new UnsupportedOperationException();\n-    }\n-\n-    private void checkSerializationTypeFromRemote() {\n-\n-    }\n-\n-    @Override\n-    public Object decode(Channel channel, InputStream input) throws IOException {\n-        ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType)\n-                .deserialize(channel.getUrl(), input);\n-        this.put(SERIALIZATION_ID_KEY, serializationType);\n-\n-        String dubboVersion = in.readUTF();\n-        request.setVersion(dubboVersion);\n-        setAttachment(DUBBO_VERSION_KEY, dubboVersion);\n-\n-        String path = in.readUTF();\n-        setAttachment(PATH_KEY, path);\n-        String version = in.readUTF();\n-        setAttachment(VERSION_KEY, version);\n-\n-        setMethodName(in.readUTF());\n-\n-        String desc = in.readUTF();\n-        setParameterTypesDesc(desc);\n-\n-        try {\n-            if (ConfigurationUtils.getSystemConfiguration().getBoolean(SERIALIZATION_SECURITY_CHECK_KEY, false)) {\n-                CodecSupport.checkSerialization(path, version, serializationType);\n-            }\n-            Object[] args = DubboCodec.EMPTY_OBJECT_ARRAY;\n-            Class<?>[] pts = DubboCodec.EMPTY_CLASS_ARRAY;\n-            if (desc.length() > 0) {\n-//                if (RpcUtils.isGenericCall(path, getMethodName()) || RpcUtils.isEcho(path, getMethodName())) {\n-//                    pts = ReflectUtils.desc2classArray(desc);\n-//                } else {\n-                ServiceRepository repository = ApplicationModel.getServiceRepository();\n-                ServiceDescriptor serviceDescriptor = repository.lookupService(path);\n-                if (serviceDescriptor != null) {\n-                    MethodDescriptor methodDescriptor = serviceDescriptor.getMethod(getMethodName(), desc);\n-                    if (methodDescriptor != null) {\n-                        pts = methodDescriptor.getParameterClasses();\n-                        this.setReturnTypes(methodDescriptor.getReturnTypes());\n-                    }\n-                }\n-                if (pts == DubboCodec.EMPTY_CLASS_ARRAY) {\n-                    if (!RpcUtils.isGenericCall(desc, getMethodName()) && !RpcUtils.isEcho(desc, getMethodName())) {\n-                        throw new IllegalArgumentException(\"Service not found:\" + path + \", \" + getMethodName());\n-                    }\n-                    pts = ReflectUtils.desc2classArray(desc);\n-                }\n-//                }\n-\n-                args = new Object[pts.length];\n-                for (int i = 0; i < args.length; i++) {\n-                    try {\n-                        args[i] = in.readObject(pts[i]);\n-                    } catch (Exception e) {\n-                        if (log.isWarnEnabled()) {\n-                            log.warn(\"Decode argument failed: \" + e.getMessage(), e);\n-                        }\n-                    }\n-                }\n-            }\n-            setParameterTypes(pts);\n-\n-            Map<String, Object> map = in.readAttachments();\n-            if (map != null && map.size() > 0) {\n-                Map<String, Object> attachment = getObjectAttachments();\n-                if (attachment == null) {\n-                    attachment = new HashMap<>();\n-                }\n-                attachment.putAll(map);\n-                setObjectAttachments(attachment);\n-            }\n-\n-            //decode argument ,may be callback\n-            for (int i = 0; i < args.length; i++) {\n-                args[i] = decodeInvocationArgument(channel, this, pts, i, args[i]);\n-            }\n-\n-            setArguments(args);\n-            String targetServiceName = buildKey((String) getAttachment(PATH_KEY),\n-                    getAttachment(GROUP_KEY),\n-                    getAttachment(VERSION_KEY));\n-            setTargetServiceUniqueName(targetServiceName);\n-        } catch (ClassNotFoundException e) {\n-            throw new IOException(StringUtils.toString(\"Read invocation data failed.\", e));\n-        } finally {\n-            if (in instanceof Cleanable) {\n-                ((Cleanable) in).cleanup();\n-            }\n-        }\n-        return this;\n-    }\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+\r\n+import org.apache.dubbo.common.config.ConfigurationUtils;\r\n+import org.apache.dubbo.common.logger.Logger;\r\n+import org.apache.dubbo.common.logger.LoggerFactory;\r\n+import org.apache.dubbo.common.serialize.Cleanable;\r\n+import org.apache.dubbo.common.serialize.ObjectInput;\r\n+import org.apache.dubbo.common.utils.Assert;\r\n+import org.apache.dubbo.common.utils.ReflectUtils;\r\n+import org.apache.dubbo.common.utils.StringUtils;\r\n+import org.apache.dubbo.remoting.Channel;\r\n+import org.apache.dubbo.remoting.Codec;\r\n+import org.apache.dubbo.remoting.Decodeable;\r\n+import org.apache.dubbo.remoting.exchange.Request;\r\n+import org.apache.dubbo.remoting.transport.CodecSupport;\r\n+import org.apache.dubbo.rpc.RpcInvocation;\r\n+import org.apache.dubbo.rpc.model.ApplicationModel;\r\n+import org.apache.dubbo.rpc.model.MethodDescriptor;\r\n+import org.apache.dubbo.rpc.model.ServiceDescriptor;\r\n+import org.apache.dubbo.rpc.model.ServiceRepository;\r\n+import org.apache.dubbo.rpc.support.RpcUtils;\r\n+\r\n+import java.io.IOException;\r\n+import java.io.InputStream;\r\n+import java.io.OutputStream;\r\n+import java.util.HashMap;\r\n+import java.util.Map;\r\n+\r\n+import static org.apache.dubbo.common.URL.buildKey;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;\r\n+import static org.apache.dubbo.rpc.Constants.SERIALIZATION_ID_KEY;\r\n+import static org.apache.dubbo.rpc.Constants.SERIALIZATION_SECURITY_CHECK_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.CallbackServiceCodec.decodeInvocationArgument;\r\n+\r\n+public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Decodeable {\r\n+\r\n+    private static final Logger log = LoggerFactory.getLogger(DecodeableRpcInvocation.class);\r\n+\r\n+    private Channel channel;\r\n+\r\n+    private byte serializationType;\r\n+\r\n+    private InputStream inputStream;\r\n+\r\n+    private Request request;\r\n+\r\n+    private volatile boolean hasDecoded;\r\n+\r\n+    public DecodeableRpcInvocation(Channel channel, Request request, InputStream is, byte id) {\r\n+        Assert.notNull(channel, \"channel == null\");\r\n+        Assert.notNull(request, \"request == null\");\r\n+        Assert.notNull(is, \"inputStream == null\");\r\n+        this.channel = channel;\r\n+        this.request = request;\r\n+        this.inputStream = is;\r\n+        this.serializationType = id;\r\n+    }\r\n+\r\n+    @Override\r\n+    public void decode() throws Exception {\r\n+        if (!hasDecoded && channel != null && inputStream != null) {\r\n+            try {\r\n+                decode(channel, inputStream);\r\n+            } catch (Throwable e) {\r\n+                if (log.isWarnEnabled()) {\r\n+                    log.warn(\"Decode rpc invocation failed: \" + e.getMessage(), e);\r\n+                }\r\n+                request.setBroken(true);\r\n+                request.setData(e);\r\n+            } finally {\r\n+                hasDecoded = true;\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public void encode(Channel channel, OutputStream output, Object message) throws IOException {\r\n+        throw new UnsupportedOperationException();\r\n+    }\r\n+\r\n+    private void checkSerializationTypeFromRemote() {\r\n+\r\n+    }\r\n+\r\n+    @Override\r\n+    public Object decode(Channel channel, InputStream input) throws IOException {\r\n+        ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType)\r\n+                .deserialize(channel.getUrl(), input);\r\n+        this.put(SERIALIZATION_ID_KEY, serializationType);\r\n+\r\n+        String dubboVersion = in.readUTF();\r\n+        request.setVersion(dubboVersion);\r\n+        setAttachment(DUBBO_VERSION_KEY, dubboVersion);\r\n+\r\n+        String path = in.readUTF();\r\n+        setAttachment(PATH_KEY, path);\r\n+        String version = in.readUTF();\r\n+        setAttachment(VERSION_KEY, version);\r\n+\r\n+        setMethodName(in.readUTF());\r\n+\r\n+        String desc = in.readUTF();\r\n+        setParameterTypesDesc(desc);\r\n+\r\n+        try {\r\n+            if (ConfigurationUtils.getSystemConfiguration().getBoolean(SERIALIZATION_SECURITY_CHECK_KEY, false)) {\r\n+                CodecSupport.checkSerialization(path, version, serializationType);\r\n+            }\r\n+            Object[] args = DubboCodec.EMPTY_OBJECT_ARRAY;\r\n+            Class<?>[] pts = DubboCodec.EMPTY_CLASS_ARRAY;\r\n+            if (desc.length() > 0) {\r\n+//                if (RpcUtils.isGenericCall(path, getMethodName()) || RpcUtils.isEcho(path, getMethodName())) {\r\n+//                    pts = ReflectUtils.desc2classArray(desc);\r\n+//                } else {\r\n+                ServiceRepository repository = ApplicationModel.getServiceRepository();\r\n+                ServiceDescriptor serviceDescriptor = repository.lookupService(path);\r\n+                if (serviceDescriptor != null) {\r\n+                    MethodDescriptor methodDescriptor = serviceDescriptor.getMethod(getMethodName(), desc);\r\n+                    if (methodDescriptor != null) {\r\n+                        pts = methodDescriptor.getParameterClasses();\r\n+                        this.setReturnTypes(methodDescriptor.getReturnTypes());\r\n+                    }\r\n+                }\r\n+                if (pts == DubboCodec.EMPTY_CLASS_ARRAY) {\r\n+                    if (!RpcUtils.isGenericCall(desc, getMethodName()) && !RpcUtils.isEcho(desc, getMethodName())) {\r\n+                        throw new IllegalArgumentException(\"Service not found:\" + path + \", \" + getMethodName());\r\n+                    }\r\n+                    pts = ReflectUtils.desc2classArray(desc);\r\n+                }\r\n+//                }\r\n+\r\n+                args = new Object[pts.length];\r\n+                for (int i = 0; i < args.length; i++) {\r\n+                    try {\r\n+                        args[i] = in.readObject(pts[i]);\r\n+                    } catch (Exception e) {\r\n+                        if (log.isWarnEnabled()) {\r\n+                            log.warn(\"Decode argument failed: \" + e.getMessage(), e);\r\n+                        }\r\n+                    }\r\n+                }\r\n+            }\r\n+            setParameterTypes(pts);\r\n+\r\n+            Map<String, Object> map = in.readAttachments();\r\n+            if (map != null && map.size() > 0) {\r\n+                Map<String, Object> attachment = getObjectAttachments();\r\n+                if (attachment == null) {\r\n+                    attachment = new HashMap<>();\r\n+                }\r\n+                attachment.putAll(map);\r\n+                setObjectAttachments(attachment);\r\n+            }\r\n+\r\n+            //decode argument ,may be callback\r\n+            for (int i = 0; i < args.length; i++) {\r\n+                args[i] = decodeInvocationArgument(channel, this, pts, i, args[i]);\r\n+            }\r\n+\r\n+            setArguments(args);\r\n+            String targetServiceName = buildKey((String) getAttachment(PATH_KEY),\r\n+                    getAttachment(GROUP_KEY),\r\n+                    getAttachment(VERSION_KEY));\r\n+            setTargetServiceUniqueName(targetServiceName);\r\n+        } catch (ClassNotFoundException e) {\r\n+            throw new IOException(StringUtils.toString(\"Read invocation data failed.\", e));\r\n+        } finally {\r\n+            if (in instanceof Cleanable) {\r\n+                ((Cleanable) in).cleanup();\r\n+            }\r\n+        }\r\n+        return this;\r\n+    }\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,184 +1,184 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-import org.apache.dubbo.common.config.ConfigurationUtils;\n-import org.apache.dubbo.common.logger.Logger;\n-import org.apache.dubbo.common.logger.LoggerFactory;\n-import org.apache.dubbo.common.serialize.Cleanable;\n-import org.apache.dubbo.common.serialize.ObjectInput;\n-import org.apache.dubbo.common.utils.ArrayUtils;\n-import org.apache.dubbo.common.utils.Assert;\n-import org.apache.dubbo.common.utils.StringUtils;\n-import org.apache.dubbo.remoting.Channel;\n-import org.apache.dubbo.remoting.Codec;\n-import org.apache.dubbo.remoting.Decodeable;\n-import org.apache.dubbo.remoting.exchange.Response;\n-import org.apache.dubbo.remoting.transport.CodecSupport;\n-import org.apache.dubbo.rpc.AppResponse;\n-import org.apache.dubbo.rpc.Invocation;\n-import org.apache.dubbo.rpc.RpcInvocation;\n-import org.apache.dubbo.rpc.support.RpcUtils;\n-\n-import java.io.IOException;\n-import java.io.InputStream;\n-import java.io.OutputStream;\n-import java.lang.reflect.Type;\n-\n-import static org.apache.dubbo.rpc.Constants.SERIALIZATION_ID_KEY;\n-import static org.apache.dubbo.rpc.Constants.SERIALIZATION_SECURITY_CHECK_KEY;\n-\n-public class DecodeableRpcResult extends AppResponse implements Codec, Decodeable {\n-\n-    private static final Logger log = LoggerFactory.getLogger(DecodeableRpcResult.class);\n-\n-    private Channel channel;\n-\n-    private byte serializationType;\n-\n-    private InputStream inputStream;\n-\n-    private Response response;\n-\n-    private Invocation invocation;\n-\n-    private volatile boolean hasDecoded;\n-\n-    public DecodeableRpcResult(Channel channel, Response response, InputStream is, Invocation invocation, byte id) {\n-        Assert.notNull(channel, \"channel == null\");\n-        Assert.notNull(response, \"response == null\");\n-        Assert.notNull(is, \"inputStream == null\");\n-        this.channel = channel;\n-        this.response = response;\n-        this.inputStream = is;\n-        this.invocation = invocation;\n-        this.serializationType = id;\n-    }\n-\n-    @Override\n-    public void encode(Channel channel, OutputStream output, Object message) throws IOException {\n-        throw new UnsupportedOperationException();\n-    }\n-\n-    @Override\n-    public Object decode(Channel channel, InputStream input) throws IOException {\n-        if (log.isDebugEnabled()) {\n-            Thread thread = Thread.currentThread();\n-            log.debug(\"Decoding in thread -- [\" + thread.getName() + \"#\" + thread.getId() + \"]\");\n-        }\n-\n-        ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType)\n-                .deserialize(channel.getUrl(), input);\n-\n-        byte flag = in.readByte();\n-        switch (flag) {\n-            case DubboCodec.RESPONSE_NULL_VALUE:\n-                break;\n-            case DubboCodec.RESPONSE_VALUE:\n-                handleValue(in);\n-                break;\n-            case DubboCodec.RESPONSE_WITH_EXCEPTION:\n-                handleException(in);\n-                break;\n-            case DubboCodec.RESPONSE_NULL_VALUE_WITH_ATTACHMENTS:\n-                handleAttachment(in);\n-                break;\n-            case DubboCodec.RESPONSE_VALUE_WITH_ATTACHMENTS:\n-                handleValue(in);\n-                handleAttachment(in);\n-                break;\n-            case DubboCodec.RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS:\n-                handleException(in);\n-                handleAttachment(in);\n-                break;\n-            default:\n-                throw new IOException(\"Unknown result flag, expect '0' '1' '2' '3' '4' '5', but received: \" + flag);\n-        }\n-        if (in instanceof Cleanable) {\n-            ((Cleanable) in).cleanup();\n-        }\n-        return this;\n-    }\n-\n-    @Override\n-    public void decode() throws Exception {\n-        if (!hasDecoded && channel != null && inputStream != null) {\n-            try {\n-                if (ConfigurationUtils.getSystemConfiguration().getBoolean(SERIALIZATION_SECURITY_CHECK_KEY, false)) {\n-                    Object serializationType_obj = invocation.get(SERIALIZATION_ID_KEY);\n-                    if (serializationType_obj != null) {\n-                        if ((byte) serializationType_obj != serializationType) {\n-                            throw new IOException(\"Unexpected serialization id:\" + serializationType + \" received from network, please check if the peer send the right id.\");\n-                        }\n-                    }\n-                }\n-                decode(channel, inputStream);\n-            } catch (Throwable e) {\n-                if (log.isWarnEnabled()) {\n-                    log.warn(\"Decode rpc result failed: \" + e.getMessage(), e);\n-                }\n-                response.setStatus(Response.CLIENT_ERROR);\n-                response.setErrorMessage(StringUtils.toString(e));\n-            } finally {\n-                hasDecoded = true;\n-            }\n-        }\n-    }\n-\n-    private void handleValue(ObjectInput in) throws IOException {\n-        try {\n-            Type[] returnTypes;\n-            if (invocation instanceof RpcInvocation) {\n-                returnTypes = ((RpcInvocation) invocation).getReturnTypes();\n-            } else {\n-                returnTypes = RpcUtils.getReturnTypes(invocation);\n-            }\n-            Object value = null;\n-            if (ArrayUtils.isEmpty(returnTypes)) {\n-                // This almost never happens?\n-                value = in.readObject();\n-            } else if (returnTypes.length == 1) {\n-                value = in.readObject((Class<?>) returnTypes[0]);\n-            } else {\n-                value = in.readObject((Class<?>) returnTypes[0], returnTypes[1]);\n-            }\n-            setValue(value);\n-        } catch (ClassNotFoundException e) {\n-            rethrow(e);\n-        }\n-    }\n-\n-    private void handleException(ObjectInput in) throws IOException {\n-        try {\n-            setException(in.readThrowable());\n-        } catch (ClassNotFoundException e) {\n-            rethrow(e);\n-        }\n-    }\n-\n-    private void handleAttachment(ObjectInput in) throws IOException {\n-        try {\n-            addObjectAttachments(in.readAttachments());\n-        } catch (ClassNotFoundException e) {\n-            rethrow(e);\n-        }\n-    }\n-\n-    private void rethrow(Exception e) throws IOException {\n-        throw new IOException(StringUtils.toString(\"Read response data failed.\", e));\n-    }\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+import org.apache.dubbo.common.config.ConfigurationUtils;\r\n+import org.apache.dubbo.common.logger.Logger;\r\n+import org.apache.dubbo.common.logger.LoggerFactory;\r\n+import org.apache.dubbo.common.serialize.Cleanable;\r\n+import org.apache.dubbo.common.serialize.ObjectInput;\r\n+import org.apache.dubbo.common.utils.ArrayUtils;\r\n+import org.apache.dubbo.common.utils.Assert;\r\n+import org.apache.dubbo.common.utils.StringUtils;\r\n+import org.apache.dubbo.remoting.Channel;\r\n+import org.apache.dubbo.remoting.Codec;\r\n+import org.apache.dubbo.remoting.Decodeable;\r\n+import org.apache.dubbo.remoting.exchange.Response;\r\n+import org.apache.dubbo.remoting.transport.CodecSupport;\r\n+import org.apache.dubbo.rpc.AppResponse;\r\n+import org.apache.dubbo.rpc.Invocation;\r\n+import org.apache.dubbo.rpc.RpcInvocation;\r\n+import org.apache.dubbo.rpc.support.RpcUtils;\r\n+\r\n+import java.io.IOException;\r\n+import java.io.InputStream;\r\n+import java.io.OutputStream;\r\n+import java.lang.reflect.Type;\r\n+\r\n+import static org.apache.dubbo.rpc.Constants.SERIALIZATION_ID_KEY;\r\n+import static org.apache.dubbo.rpc.Constants.SERIALIZATION_SECURITY_CHECK_KEY;\r\n+\r\n+public class DecodeableRpcResult extends AppResponse implements Codec, Decodeable {\r\n+\r\n+    private static final Logger log = LoggerFactory.getLogger(DecodeableRpcResult.class);\r\n+\r\n+    private Channel channel;\r\n+\r\n+    private byte serializationType;\r\n+\r\n+    private InputStream inputStream;\r\n+\r\n+    private Response response;\r\n+\r\n+    private Invocation invocation;\r\n+\r\n+    private volatile boolean hasDecoded;\r\n+\r\n+    public DecodeableRpcResult(Channel channel, Response response, InputStream is, Invocation invocation, byte id) {\r\n+        Assert.notNull(channel, \"channel == null\");\r\n+        Assert.notNull(response, \"response == null\");\r\n+        Assert.notNull(is, \"inputStream == null\");\r\n+        this.channel = channel;\r\n+        this.response = response;\r\n+        this.inputStream = is;\r\n+        this.invocation = invocation;\r\n+        this.serializationType = id;\r\n+    }\r\n+\r\n+    @Override\r\n+    public void encode(Channel channel, OutputStream output, Object message) throws IOException {\r\n+        throw new UnsupportedOperationException();\r\n+    }\r\n+\r\n+    @Override\r\n+    public Object decode(Channel channel, InputStream input) throws IOException {\r\n+        if (log.isDebugEnabled()) {\r\n+            Thread thread = Thread.currentThread();\r\n+            log.debug(\"Decoding in thread -- [\" + thread.getName() + \"#\" + thread.getId() + \"]\");\r\n+        }\r\n+\r\n+        ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType)\r\n+                .deserialize(channel.getUrl(), input);\r\n+\r\n+        byte flag = in.readByte();\r\n+        switch (flag) {\r\n+            case DubboCodec.RESPONSE_NULL_VALUE:\r\n+                break;\r\n+            case DubboCodec.RESPONSE_VALUE:\r\n+                handleValue(in);\r\n+                break;\r\n+            case DubboCodec.RESPONSE_WITH_EXCEPTION:\r\n+                handleException(in);\r\n+                break;\r\n+            case DubboCodec.RESPONSE_NULL_VALUE_WITH_ATTACHMENTS:\r\n+                handleAttachment(in);\r\n+                break;\r\n+            case DubboCodec.RESPONSE_VALUE_WITH_ATTACHMENTS:\r\n+                handleValue(in);\r\n+                handleAttachment(in);\r\n+                break;\r\n+            case DubboCodec.RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS:\r\n+                handleException(in);\r\n+                handleAttachment(in);\r\n+                break;\r\n+            default:\r\n+                throw new IOException(\"Unknown result flag, expect '0' '1' '2' '3' '4' '5', but received: \" + flag);\r\n+        }\r\n+        if (in instanceof Cleanable) {\r\n+            ((Cleanable) in).cleanup();\r\n+        }\r\n+        return this;\r\n+    }\r\n+\r\n+    @Override\r\n+    public void decode() throws Exception {\r\n+        if (!hasDecoded && channel != null && inputStream != null) {\r\n+            try {\r\n+                if (ConfigurationUtils.getSystemConfiguration().getBoolean(SERIALIZATION_SECURITY_CHECK_KEY, false)) {\r\n+                    Object serializationType_obj = invocation.get(SERIALIZATION_ID_KEY);\r\n+                    if (serializationType_obj != null) {\r\n+                        if ((byte) serializationType_obj != serializationType) {\r\n+                            throw new IOException(\"Unexpected serialization id:\" + serializationType + \" received from network, please check if the peer send the right id.\");\r\n+                        }\r\n+                    }\r\n+                }\r\n+                decode(channel, inputStream);\r\n+            } catch (Throwable e) {\r\n+                if (log.isWarnEnabled()) {\r\n+                    log.warn(\"Decode rpc result failed: \" + e.getMessage(), e);\r\n+                }\r\n+                response.setStatus(Response.CLIENT_ERROR);\r\n+                response.setErrorMessage(StringUtils.toString(e));\r\n+            } finally {\r\n+                hasDecoded = true;\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+    private void handleValue(ObjectInput in) throws IOException {\r\n+        try {\r\n+            Type[] returnTypes;\r\n+            if (invocation instanceof RpcInvocation) {\r\n+                returnTypes = ((RpcInvocation) invocation).getReturnTypes();\r\n+            } else {\r\n+                returnTypes = RpcUtils.getReturnTypes(invocation);\r\n+            }\r\n+            Object value = null;\r\n+            if (ArrayUtils.isEmpty(returnTypes)) {\r\n+                // This almost never happens?\r\n+                value = in.readObject();\r\n+            } else if (returnTypes.length == 1) {\r\n+                value = in.readObject((Class<?>) returnTypes[0]);\r\n+            } else {\r\n+                value = in.readObject((Class<?>) returnTypes[0], returnTypes[1]);\r\n+            }\r\n+            setValue(value);\r\n+        } catch (ClassNotFoundException e) {\r\n+            rethrow(e);\r\n+        }\r\n+    }\r\n+\r\n+    private void handleException(ObjectInput in) throws IOException {\r\n+        try {\r\n+            setException(in.readThrowable());\r\n+        } catch (ClassNotFoundException e) {\r\n+            rethrow(e);\r\n+        }\r\n+    }\r\n+\r\n+    private void handleAttachment(ObjectInput in) throws IOException {\r\n+        try {\r\n+            addObjectAttachments(in.readAttachments());\r\n+        } catch (ClassNotFoundException e) {\r\n+            rethrow(e);\r\n+        }\r\n+    }\r\n+\r\n+    private void rethrow(Exception e) throws IOException {\r\n+        throw new IOException(StringUtils.toString(\"Read response data failed.\", e));\r\n+    }\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,248 +1,248 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-import org.apache.dubbo.common.Version;\n-import org.apache.dubbo.common.io.Bytes;\n-import org.apache.dubbo.common.io.UnsafeByteArrayInputStream;\n-import org.apache.dubbo.common.logger.Logger;\n-import org.apache.dubbo.common.logger.LoggerFactory;\n-import org.apache.dubbo.common.serialize.ObjectInput;\n-import org.apache.dubbo.common.serialize.ObjectOutput;\n-import org.apache.dubbo.common.serialize.Serialization;\n-import org.apache.dubbo.common.utils.StringUtils;\n-import org.apache.dubbo.remoting.Channel;\n-import org.apache.dubbo.remoting.exchange.Request;\n-import org.apache.dubbo.remoting.exchange.Response;\n-import org.apache.dubbo.remoting.exchange.codec.ExchangeCodec;\n-import org.apache.dubbo.remoting.transport.CodecSupport;\n-import org.apache.dubbo.rpc.AppResponse;\n-import org.apache.dubbo.rpc.Invocation;\n-import org.apache.dubbo.rpc.Result;\n-import org.apache.dubbo.rpc.RpcInvocation;\n-\n-import java.io.ByteArrayInputStream;\n-import java.io.IOException;\n-import java.io.InputStream;\n-\n-import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.CallbackServiceCodec.encodeInvocationArgument;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.DECODE_IN_IO_THREAD_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.DEFAULT_DECODE_IN_IO_THREAD;\n-\n-/**\n- * Dubbo codec.\n- */\n-public class DubboCodec extends ExchangeCodec {\n-\n-    public static final String NAME = \"dubbo\";\n-    public static final String DUBBO_VERSION = Version.getProtocolVersion();\n-    public static final byte RESPONSE_WITH_EXCEPTION = 0;\n-    public static final byte RESPONSE_VALUE = 1;\n-    public static final byte RESPONSE_NULL_VALUE = 2;\n-    public static final byte RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS = 3;\n-    public static final byte RESPONSE_VALUE_WITH_ATTACHMENTS = 4;\n-    public static final byte RESPONSE_NULL_VALUE_WITH_ATTACHMENTS = 5;\n-    public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];\n-    public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];\n-    private static final Logger log = LoggerFactory.getLogger(DubboCodec.class);\n-\n-    @Override\n-    protected Object decodeBody(Channel channel, InputStream is, byte[] header) throws IOException {\n-        byte flag = header[2], proto = (byte) (flag & SERIALIZATION_MASK);\n-        // get request id.\n-        long id = Bytes.bytes2long(header, 4);\n-        if ((flag & FLAG_REQUEST) == 0) {\n-            // decode response.\n-            Response res = new Response(id);\n-            if ((flag & FLAG_EVENT) != 0) {\n-                res.setEvent(true);\n-            }\n-            // get status.\n-            byte status = header[3];\n-            res.setStatus(status);\n-            try {\n-                if (status == Response.OK) {\n-                    Object data;\n-                    if (res.isEvent()) {\n-                        byte[] eventPayload = CodecSupport.getPayload(is);\n-                        if (CodecSupport.isHeartBeat(eventPayload, proto)) {\n-                            // heart beat response data is always null;\n-                            data = null;\n-                        } else {\n-                            ObjectInput in = CodecSupport.deserialize(channel.getUrl(), new ByteArrayInputStream(eventPayload), proto);\n-                            data = decodeEventData(channel, in, eventPayload);\n-                        }\n-                    } else {\n-                        DecodeableRpcResult result;\n-                        if (channel.getUrl().getParameter(DECODE_IN_IO_THREAD_KEY, DEFAULT_DECODE_IN_IO_THREAD)) {\n-                            result = new DecodeableRpcResult(channel, res, is,\n-                                    (Invocation) getRequestData(id), proto);\n-                            result.decode();\n-                        } else {\n-                            result = new DecodeableRpcResult(channel, res,\n-                                    new UnsafeByteArrayInputStream(readMessageData(is)),\n-                                    (Invocation) getRequestData(id), proto);\n-                        }\n-                        data = result;\n-                    }\n-                    res.setResult(data);\n-                } else {\n-                    ObjectInput in = CodecSupport.deserialize(channel.getUrl(), is, proto);\n-                    res.setErrorMessage(in.readUTF());\n-                }\n-            } catch (Throwable t) {\n-                if (log.isWarnEnabled()) {\n-                    log.warn(\"Decode response failed: \" + t.getMessage(), t);\n-                }\n-                res.setStatus(Response.CLIENT_ERROR);\n-                res.setErrorMessage(StringUtils.toString(t));\n-            }\n-            return res;\n-        } else {\n-            // decode request.\n-            Request req = new Request(id);\n-            req.setVersion(Version.getProtocolVersion());\n-            req.setTwoWay((flag & FLAG_TWOWAY) != 0);\n-            if ((flag & FLAG_EVENT) != 0) {\n-                req.setEvent(true);\n-            }\n-            try {\n-                Object data;\n-                if (req.isEvent()) {\n-                    byte[] eventPayload = CodecSupport.getPayload(is);\n-                    if (CodecSupport.isHeartBeat(eventPayload, proto)) {\n-                        // heart beat response data is always null;\n-                        data = null;\n-                    } else {\n-                        ObjectInput in = CodecSupport.deserialize(channel.getUrl(), new ByteArrayInputStream(eventPayload), proto);\n-                        data = decodeEventData(channel, in, eventPayload);\n-                    }\n-                } else {\n-                    DecodeableRpcInvocation inv;\n-                    if (channel.getUrl().getParameter(DECODE_IN_IO_THREAD_KEY, DEFAULT_DECODE_IN_IO_THREAD)) {\n-                        inv = new DecodeableRpcInvocation(channel, req, is, proto);\n-                        inv.decode();\n-                    } else {\n-                        inv = new DecodeableRpcInvocation(channel, req,\n-                                new UnsafeByteArrayInputStream(readMessageData(is)), proto);\n-                    }\n-                    data = inv;\n-                }\n-                req.setData(data);\n-            } catch (Throwable t) {\n-                if (log.isWarnEnabled()) {\n-                    log.warn(\"Decode request failed: \" + t.getMessage(), t);\n-                }\n-                // bad request\n-                req.setBroken(true);\n-                req.setData(t);\n-            }\n-\n-            return req;\n-        }\n-    }\n-\n-    private byte[] readMessageData(InputStream is) throws IOException {\n-        if (is.available() > 0) {\n-            byte[] result = new byte[is.available()];\n-            is.read(result);\n-            return result;\n-        }\n-        return new byte[]{};\n-    }\n-\n-    @Override\n-    protected void encodeRequestData(Channel channel, ObjectOutput out, Object data) throws IOException {\n-        encodeRequestData(channel, out, data, DUBBO_VERSION);\n-    }\n-\n-    @Override\n-    protected void encodeResponseData(Channel channel, ObjectOutput out, Object data) throws IOException {\n-        encodeResponseData(channel, out, data, DUBBO_VERSION);\n-    }\n-\n-    @Override\n-    protected void encodeRequestData(Channel channel, ObjectOutput out, Object data, String version) throws IOException {\n-        RpcInvocation inv = (RpcInvocation) data;\n-\n-        out.writeUTF(version);\n-        // https://github.com/apache/dubbo/issues/6138\n-        String serviceName = inv.getAttachment(INTERFACE_KEY);\n-        if (serviceName == null) {\n-            serviceName = inv.getAttachment(PATH_KEY);\n-        }\n-        out.writeUTF(serviceName);\n-        out.writeUTF(inv.getAttachment(VERSION_KEY));\n-\n-        out.writeUTF(inv.getMethodName());\n-        out.writeUTF(inv.getParameterTypesDesc());\n-        Object[] args = inv.getArguments();\n-        if (args != null) {\n-            for (int i = 0; i < args.length; i++) {\n-                out.writeObject(encodeInvocationArgument(channel, inv, i));\n-            }\n-        }\n-        out.writeAttachments(inv.getObjectAttachments());\n-    }\n-\n-    @Override\n-    protected void encodeResponseData(Channel channel, ObjectOutput out, Object data, String version) throws IOException {\n-        Result result = (Result) data;\n-        // currently, the version value in Response records the version of Request\n-        boolean attach = Version.isSupportResponseAttachment(version);\n-        Throwable th = result.getException();\n-        if (th == null) {\n-            Object ret = result.getValue();\n-            if (ret == null) {\n-                out.writeByte(attach ? RESPONSE_NULL_VALUE_WITH_ATTACHMENTS : RESPONSE_NULL_VALUE);\n-            } else {\n-                out.writeByte(attach ? RESPONSE_VALUE_WITH_ATTACHMENTS : RESPONSE_VALUE);\n-                out.writeObject(ret);\n-            }\n-        } else {\n-            out.writeByte(attach ? RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS : RESPONSE_WITH_EXCEPTION);\n-            out.writeThrowable(th);\n-        }\n-\n-        if (attach) {\n-            // returns current version of Response to consumer side.\n-            result.getObjectAttachments().put(DUBBO_VERSION_KEY, Version.getProtocolVersion());\n-            out.writeAttachments(result.getObjectAttachments());\n-        }\n-    }\n-\n-    @Override\n-    protected Serialization getSerialization(Channel channel, Request req) {\n-        if (!(req.getData() instanceof Invocation)) {\n-            return super.getSerialization(channel, req);\n-        }\n-        return DubboCodecSupport.getRequestSerialization(channel.getUrl(), (Invocation) req.getData());\n-    }\n-\n-    @Override\n-    protected Serialization getSerialization(Channel channel, Response res) {\n-        if (!(res.getResult() instanceof AppResponse)) {\n-            return super.getSerialization(channel, res);\n-        }\n-        return DubboCodecSupport.getResponseSerialization(channel.getUrl(), (AppResponse) res.getResult());\n-    }\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+import org.apache.dubbo.common.Version;\r\n+import org.apache.dubbo.common.io.Bytes;\r\n+import org.apache.dubbo.common.io.UnsafeByteArrayInputStream;\r\n+import org.apache.dubbo.common.logger.Logger;\r\n+import org.apache.dubbo.common.logger.LoggerFactory;\r\n+import org.apache.dubbo.common.serialize.ObjectInput;\r\n+import org.apache.dubbo.common.serialize.ObjectOutput;\r\n+import org.apache.dubbo.common.serialize.Serialization;\r\n+import org.apache.dubbo.common.utils.StringUtils;\r\n+import org.apache.dubbo.remoting.Channel;\r\n+import org.apache.dubbo.remoting.exchange.Request;\r\n+import org.apache.dubbo.remoting.exchange.Response;\r\n+import org.apache.dubbo.remoting.exchange.codec.ExchangeCodec;\r\n+import org.apache.dubbo.remoting.transport.CodecSupport;\r\n+import org.apache.dubbo.rpc.AppResponse;\r\n+import org.apache.dubbo.rpc.Invocation;\r\n+import org.apache.dubbo.rpc.Result;\r\n+import org.apache.dubbo.rpc.RpcInvocation;\r\n+\r\n+import java.io.ByteArrayInputStream;\r\n+import java.io.IOException;\r\n+import java.io.InputStream;\r\n+\r\n+import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.CallbackServiceCodec.encodeInvocationArgument;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.DECODE_IN_IO_THREAD_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.DEFAULT_DECODE_IN_IO_THREAD;\r\n+\r\n+/**\r\n+ * Dubbo codec.\r\n+ */\r\n+public class DubboCodec extends ExchangeCodec {\r\n+\r\n+    public static final String NAME = \"dubbo\";\r\n+    public static final String DUBBO_VERSION = Version.getProtocolVersion();\r\n+    public static final byte RESPONSE_WITH_EXCEPTION = 0;\r\n+    public static final byte RESPONSE_VALUE = 1;\r\n+    public static final byte RESPONSE_NULL_VALUE = 2;\r\n+    public static final byte RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS = 3;\r\n+    public static final byte RESPONSE_VALUE_WITH_ATTACHMENTS = 4;\r\n+    public static final byte RESPONSE_NULL_VALUE_WITH_ATTACHMENTS = 5;\r\n+    public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];\r\n+    public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];\r\n+    private static final Logger log = LoggerFactory.getLogger(DubboCodec.class);\r\n+\r\n+    @Override\r\n+    protected Object decodeBody(Channel channel, InputStream is, byte[] header) throws IOException {\r\n+        byte flag = header[2], proto = (byte) (flag & SERIALIZATION_MASK);\r\n+        // get request id.\r\n+        long id = Bytes.bytes2long(header, 4);\r\n+        if ((flag & FLAG_REQUEST) == 0) {\r\n+            // decode response.\r\n+            Response res = new Response(id);\r\n+            if ((flag & FLAG_EVENT) != 0) {\r\n+                res.setEvent(true);\r\n+            }\r\n+            // get status.\r\n+            byte status = header[3];\r\n+            res.setStatus(status);\r\n+            try {\r\n+                if (status == Response.OK) {\r\n+                    Object data;\r\n+                    if (res.isEvent()) {\r\n+                        byte[] eventPayload = CodecSupport.getPayload(is);\r\n+                        if (CodecSupport.isHeartBeat(eventPayload, proto)) {\r\n+                            // heart beat response data is always null;\r\n+                            data = null;\r\n+                        } else {\r\n+                            ObjectInput in = CodecSupport.deserialize(channel.getUrl(), new ByteArrayInputStream(eventPayload), proto);\r\n+                            data = decodeEventData(channel, in, eventPayload);\r\n+                        }\r\n+                    } else {\r\n+                        DecodeableRpcResult result;\r\n+                        if (channel.getUrl().getParameter(DECODE_IN_IO_THREAD_KEY, DEFAULT_DECODE_IN_IO_THREAD)) {\r\n+                            result = new DecodeableRpcResult(channel, res, is,\r\n+                                    (Invocation) getRequestData(id), proto);\r\n+                            result.decode();\r\n+                        } else {\r\n+                            result = new DecodeableRpcResult(channel, res,\r\n+                                    new UnsafeByteArrayInputStream(readMessageData(is)),\r\n+                                    (Invocation) getRequestData(id), proto);\r\n+                        }\r\n+                        data = result;\r\n+                    }\r\n+                    res.setResult(data);\r\n+                } else {\r\n+                    ObjectInput in = CodecSupport.deserialize(channel.getUrl(), is, proto);\r\n+                    res.setErrorMessage(in.readUTF());\r\n+                }\r\n+            } catch (Throwable t) {\r\n+                if (log.isWarnEnabled()) {\r\n+                    log.warn(\"Decode response failed: \" + t.getMessage(), t);\r\n+                }\r\n+                res.setStatus(Response.CLIENT_ERROR);\r\n+                res.setErrorMessage(StringUtils.toString(t));\r\n+            }\r\n+            return res;\r\n+        } else {\r\n+            // decode request.\r\n+            Request req = new Request(id);\r\n+            req.setVersion(Version.getProtocolVersion());\r\n+            req.setTwoWay((flag & FLAG_TWOWAY) != 0);\r\n+            if ((flag & FLAG_EVENT) != 0) {\r\n+                req.setEvent(true);\r\n+            }\r\n+            try {\r\n+                Object data;\r\n+                if (req.isEvent()) {\r\n+                    byte[] eventPayload = CodecSupport.getPayload(is);\r\n+                    if (CodecSupport.isHeartBeat(eventPayload, proto)) {\r\n+                        // heart beat response data is always null;\r\n+                        data = null;\r\n+                    } else {\r\n+                        ObjectInput in = CodecSupport.deserialize(channel.getUrl(), new ByteArrayInputStream(eventPayload), proto);\r\n+                        data = decodeEventData(channel, in, eventPayload);\r\n+                    }\r\n+                } else {\r\n+                    DecodeableRpcInvocation inv;\r\n+                    if (channel.getUrl().getParameter(DECODE_IN_IO_THREAD_KEY, DEFAULT_DECODE_IN_IO_THREAD)) {\r\n+                        inv = new DecodeableRpcInvocation(channel, req, is, proto);\r\n+                        inv.decode();\r\n+                    } else {\r\n+                        inv = new DecodeableRpcInvocation(channel, req,\r\n+                                new UnsafeByteArrayInputStream(readMessageData(is)), proto);\r\n+                    }\r\n+                    data = inv;\r\n+                }\r\n+                req.setData(data);\r\n+            } catch (Throwable t) {\r\n+                if (log.isWarnEnabled()) {\r\n+                    log.warn(\"Decode request failed: \" + t.getMessage(), t);\r\n+                }\r\n+                // bad request\r\n+                req.setBroken(true);\r\n+                req.setData(t);\r\n+            }\r\n+\r\n+            return req;\r\n+        }\r\n+    }\r\n+\r\n+    private byte[] readMessageData(InputStream is) throws IOException {\r\n+        if (is.available() > 0) {\r\n+            byte[] result = new byte[is.available()];\r\n+            is.read(result);\r\n+            return result;\r\n+        }\r\n+        return new byte[]{};\r\n+    }\r\n+\r\n+    @Override\r\n+    protected void encodeRequestData(Channel channel, ObjectOutput out, Object data) throws IOException {\r\n+        encodeRequestData(channel, out, data, DUBBO_VERSION);\r\n+    }\r\n+\r\n+    @Override\r\n+    protected void encodeResponseData(Channel channel, ObjectOutput out, Object data) throws IOException {\r\n+        encodeResponseData(channel, out, data, DUBBO_VERSION);\r\n+    }\r\n+\r\n+    @Override\r\n+    protected void encodeRequestData(Channel channel, ObjectOutput out, Object data, String version) throws IOException {\r\n+        RpcInvocation inv = (RpcInvocation) data;\r\n+\r\n+        out.writeUTF(version);\r\n+        // https://github.com/apache/dubbo/issues/6138\r\n+        String serviceName = inv.getAttachment(INTERFACE_KEY);\r\n+        if (serviceName == null) {\r\n+            serviceName = inv.getAttachment(PATH_KEY);\r\n+        }\r\n+        out.writeUTF(serviceName);\r\n+        out.writeUTF(inv.getAttachment(VERSION_KEY));\r\n+\r\n+        out.writeUTF(inv.getMethodName());\r\n+        out.writeUTF(inv.getParameterTypesDesc());\r\n+        Object[] args = inv.getArguments();\r\n+        if (args != null) {\r\n+            for (int i = 0; i < args.length; i++) {\r\n+                out.writeObject(encodeInvocationArgument(channel, inv, i));\r\n+            }\r\n+        }\r\n+        out.writeAttachments(inv.getObjectAttachments());\r\n+    }\r\n+\r\n+    @Override\r\n+    protected void encodeResponseData(Channel channel, ObjectOutput out, Object data, String version) throws IOException {\r\n+        Result result = (Result) data;\r\n+        // currently, the version value in Response records the version of Request\r\n+        boolean attach = Version.isSupportResponseAttachment(version);\r\n+        Throwable th = result.getException();\r\n+        if (th == null) {\r\n+            Object ret = result.getValue();\r\n+            if (ret == null) {\r\n+                out.writeByte(attach ? RESPONSE_NULL_VALUE_WITH_ATTACHMENTS : RESPONSE_NULL_VALUE);\r\n+            } else {\r\n+                out.writeByte(attach ? RESPONSE_VALUE_WITH_ATTACHMENTS : RESPONSE_VALUE);\r\n+                out.writeObject(ret);\r\n+            }\r\n+        } else {\r\n+            out.writeByte(attach ? RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS : RESPONSE_WITH_EXCEPTION);\r\n+            out.writeThrowable(th);\r\n+        }\r\n+\r\n+        if (attach) {\r\n+            // returns current version of Response to consumer side.\r\n+            result.getObjectAttachments().put(DUBBO_VERSION_KEY, Version.getProtocolVersion());\r\n+            out.writeAttachments(result.getObjectAttachments());\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    protected Serialization getSerialization(Channel channel, Request req) {\r\n+        if (!(req.getData() instanceof Invocation)) {\r\n+            return super.getSerialization(channel, req);\r\n+        }\r\n+        return DubboCodecSupport.getRequestSerialization(channel.getUrl(), (Invocation) req.getData());\r\n+    }\r\n+\r\n+    @Override\r\n+    protected Serialization getSerialization(Channel channel, Response res) {\r\n+        if (!(res.getResult() instanceof AppResponse)) {\r\n+            return super.getSerialization(channel, res);\r\n+        }\r\n+        return DubboCodecSupport.getResponseSerialization(channel.getUrl(), (AppResponse) res.getResult());\r\n+    }\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/DubboCodecSupport.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/DubboCodecSupport.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,53 +1,53 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.common.extension.ExtensionLoader;\n-import org.apache.dubbo.common.serialize.Serialization;\n-import org.apache.dubbo.remoting.Constants;\n-import org.apache.dubbo.remoting.transport.CodecSupport;\n-import org.apache.dubbo.rpc.AppResponse;\n-import org.apache.dubbo.rpc.Invocation;\n-\n-import static org.apache.dubbo.rpc.Constants.INVOCATION_KEY;\n-import static org.apache.dubbo.rpc.Constants.SERIALIZATION_ID_KEY;\n-\n-public class DubboCodecSupport {\n-\n-    public static Serialization getRequestSerialization(URL url, Invocation invocation) {\n-        Object serializationType_obj = invocation.get(SERIALIZATION_ID_KEY);\n-        if (serializationType_obj != null) {\n-            return CodecSupport.getSerializationById((byte) serializationType_obj);\n-        }\n-        return ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(\n-                url.getParameter(org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION));\n-    }\n-\n-    public static Serialization getResponseSerialization(URL url, AppResponse appResponse) {\n-        Object invocation_obj = appResponse.getAttribute(INVOCATION_KEY);\n-        if (invocation_obj != null) {\n-            Invocation invocation = (Invocation) invocation_obj;\n-            Object serializationType_obj = invocation.get(SERIALIZATION_ID_KEY);\n-            if (serializationType_obj != null) {\n-                return CodecSupport.getSerializationById((byte) serializationType_obj);\n-            }\n-        }\n-        return ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(\n-                url.getParameter(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION));\n-    }\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.common.extension.ExtensionLoader;\r\n+import org.apache.dubbo.common.serialize.Serialization;\r\n+import org.apache.dubbo.remoting.Constants;\r\n+import org.apache.dubbo.remoting.transport.CodecSupport;\r\n+import org.apache.dubbo.rpc.AppResponse;\r\n+import org.apache.dubbo.rpc.Invocation;\r\n+\r\n+import static org.apache.dubbo.rpc.Constants.INVOCATION_KEY;\r\n+import static org.apache.dubbo.rpc.Constants.SERIALIZATION_ID_KEY;\r\n+\r\n+public class DubboCodecSupport {\r\n+\r\n+    public static Serialization getRequestSerialization(URL url, Invocation invocation) {\r\n+        Object serializationType_obj = invocation.get(SERIALIZATION_ID_KEY);\r\n+        if (serializationType_obj != null) {\r\n+            return CodecSupport.getSerializationById((byte) serializationType_obj);\r\n+        }\r\n+        return ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(\r\n+                url.getParameter(org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION));\r\n+    }\r\n+\r\n+    public static Serialization getResponseSerialization(URL url, AppResponse appResponse) {\r\n+        Object invocation_obj = appResponse.getAttribute(INVOCATION_KEY);\r\n+        if (invocation_obj != null) {\r\n+            Invocation invocation = (Invocation) invocation_obj;\r\n+            Object serializationType_obj = invocation.get(SERIALIZATION_ID_KEY);\r\n+            if (serializationType_obj != null) {\r\n+                return CodecSupport.getSerializationById((byte) serializationType_obj);\r\n+            }\r\n+        }\r\n+        return ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(\r\n+                url.getParameter(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION));\r\n+    }\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/DubboCountCodec.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/DubboCountCodec.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,86 +1,86 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-import org.apache.dubbo.remoting.Channel;\n-import org.apache.dubbo.remoting.Codec2;\n-import org.apache.dubbo.remoting.buffer.ChannelBuffer;\n-import org.apache.dubbo.remoting.exchange.Request;\n-import org.apache.dubbo.remoting.exchange.Response;\n-import org.apache.dubbo.remoting.exchange.support.MultiMessage;\n-import org.apache.dubbo.rpc.AppResponse;\n-import org.apache.dubbo.rpc.RpcInvocation;\n-\n-import java.io.IOException;\n-\n-import static org.apache.dubbo.rpc.Constants.INPUT_KEY;\n-import static org.apache.dubbo.rpc.Constants.OUTPUT_KEY;\n-\n-public final class DubboCountCodec implements Codec2 {\n-\n-    private DubboCodec codec = new DubboCodec();\n-\n-    @Override\n-    public void encode(Channel channel, ChannelBuffer buffer, Object msg) throws IOException {\n-        codec.encode(channel, buffer, msg);\n-    }\n-\n-    @Override\n-    public Object decode(Channel channel, ChannelBuffer buffer) throws IOException {\n-        int save = buffer.readerIndex();\n-        MultiMessage result = MultiMessage.create();\n-        do {\n-            Object obj = codec.decode(channel, buffer);\n-            if (Codec2.DecodeResult.NEED_MORE_INPUT == obj) {\n-                buffer.readerIndex(save);\n-                break;\n-            } else {\n-                result.addMessage(obj);\n-                logMessageLength(obj, buffer.readerIndex() - save);\n-                save = buffer.readerIndex();\n-            }\n-        } while (true);\n-        if (result.isEmpty()) {\n-            return Codec2.DecodeResult.NEED_MORE_INPUT;\n-        }\n-        if (result.size() == 1) {\n-            return result.get(0);\n-        }\n-        return result;\n-    }\n-\n-    private void logMessageLength(Object result, int bytes) {\n-        if (bytes <= 0) {\n-            return;\n-        }\n-        if (result instanceof Request) {\n-            try {\n-                ((RpcInvocation) ((Request) result).getData()).setAttachment(INPUT_KEY, String.valueOf(bytes));\n-            } catch (Throwable e) {\n-                /* ignore */\n-            }\n-        } else if (result instanceof Response) {\n-            try {\n-                ((AppResponse) ((Response) result).getResult()).setAttachment(OUTPUT_KEY, String.valueOf(bytes));\n-            } catch (Throwable e) {\n-                /* ignore */\n-            }\n-        }\n-    }\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+import org.apache.dubbo.remoting.Channel;\r\n+import org.apache.dubbo.remoting.Codec2;\r\n+import org.apache.dubbo.remoting.buffer.ChannelBuffer;\r\n+import org.apache.dubbo.remoting.exchange.Request;\r\n+import org.apache.dubbo.remoting.exchange.Response;\r\n+import org.apache.dubbo.remoting.exchange.support.MultiMessage;\r\n+import org.apache.dubbo.rpc.AppResponse;\r\n+import org.apache.dubbo.rpc.RpcInvocation;\r\n+\r\n+import java.io.IOException;\r\n+\r\n+import static org.apache.dubbo.rpc.Constants.INPUT_KEY;\r\n+import static org.apache.dubbo.rpc.Constants.OUTPUT_KEY;\r\n+\r\n+public final class DubboCountCodec implements Codec2 {\r\n+\r\n+    private DubboCodec codec = new DubboCodec();\r\n+\r\n+    @Override\r\n+    public void encode(Channel channel, ChannelBuffer buffer, Object msg) throws IOException {\r\n+        codec.encode(channel, buffer, msg);\r\n+    }\r\n+\r\n+    @Override\r\n+    public Object decode(Channel channel, ChannelBuffer buffer) throws IOException {\r\n+        int save = buffer.readerIndex();\r\n+        MultiMessage result = MultiMessage.create();\r\n+        do {\r\n+            Object obj = codec.decode(channel, buffer);\r\n+            if (Codec2.DecodeResult.NEED_MORE_INPUT == obj) {\r\n+                buffer.readerIndex(save);\r\n+                break;\r\n+            } else {\r\n+                result.addMessage(obj);\r\n+                logMessageLength(obj, buffer.readerIndex() - save);\r\n+                save = buffer.readerIndex();\r\n+            }\r\n+        } while (true);\r\n+        if (result.isEmpty()) {\r\n+            return Codec2.DecodeResult.NEED_MORE_INPUT;\r\n+        }\r\n+        if (result.size() == 1) {\r\n+            return result.get(0);\r\n+        }\r\n+        return result;\r\n+    }\r\n+\r\n+    private void logMessageLength(Object result, int bytes) {\r\n+        if (bytes <= 0) {\r\n+            return;\r\n+        }\r\n+        if (result instanceof Request) {\r\n+            try {\r\n+                ((RpcInvocation) ((Request) result).getData()).setAttachment(INPUT_KEY, String.valueOf(bytes));\r\n+            } catch (Throwable e) {\r\n+                /* ignore */\r\n+            }\r\n+        } else if (result instanceof Response) {\r\n+            try {\r\n+                ((AppResponse) ((Response) result).getResult()).setAttachment(OUTPUT_KEY, String.valueOf(bytes));\r\n+            } catch (Throwable e) {\r\n+                /* ignore */\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,45 +1,45 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-import org.apache.dubbo.rpc.Exporter;\n-import org.apache.dubbo.rpc.Invoker;\n-import org.apache.dubbo.rpc.protocol.AbstractExporter;\n-\n-import java.util.Map;\n-\n-/**\n- * DubboExporter\n- */\n-public class DubboExporter<T> extends AbstractExporter<T> {\n-\n-    private final String key;\n-\n-    private final Map<String, Exporter<?>> exporterMap;\n-\n-    public DubboExporter(Invoker<T> invoker, String key, Map<String, Exporter<?>> exporterMap) {\n-        super(invoker);\n-        this.key = key;\n-        this.exporterMap = exporterMap;\n-    }\n-\n-    @Override\n-    public void afterUnExport() {\n-        exporterMap.remove(key);\n-    }\n-\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+import org.apache.dubbo.rpc.Exporter;\r\n+import org.apache.dubbo.rpc.Invoker;\r\n+import org.apache.dubbo.rpc.protocol.AbstractExporter;\r\n+\r\n+import java.util.Map;\r\n+\r\n+/**\r\n+ * DubboExporter\r\n+ */\r\n+public class DubboExporter<T> extends AbstractExporter<T> {\r\n+\r\n+    private final String key;\r\n+\r\n+    private final Map<String, Exporter<?>> exporterMap;\r\n+\r\n+    public DubboExporter(Invoker<T> invoker, String key, Map<String, Exporter<?>> exporterMap) {\r\n+        super(invoker);\r\n+        this.key = key;\r\n+        this.exporterMap = exporterMap;\r\n+    }\r\n+\r\n+    @Override\r\n+    public void afterUnExport() {\r\n+        exporterMap.remove(key);\r\n+    }\r\n+\r\n }\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,183 +1,183 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.common.config.ConfigurationUtils;\n-import org.apache.dubbo.common.utils.AtomicPositiveInteger;\n-import org.apache.dubbo.remoting.Constants;\n-import org.apache.dubbo.remoting.RemotingException;\n-import org.apache.dubbo.remoting.TimeoutException;\n-import org.apache.dubbo.remoting.exchange.ExchangeClient;\n-import org.apache.dubbo.rpc.AppResponse;\n-import org.apache.dubbo.rpc.AsyncRpcResult;\n-import org.apache.dubbo.rpc.FutureContext;\n-import org.apache.dubbo.rpc.Invocation;\n-import org.apache.dubbo.rpc.Invoker;\n-import org.apache.dubbo.rpc.Result;\n-import org.apache.dubbo.rpc.RpcContext;\n-import org.apache.dubbo.rpc.RpcException;\n-import org.apache.dubbo.rpc.RpcInvocation;\n-import org.apache.dubbo.rpc.TimeoutCountDown;\n-import org.apache.dubbo.rpc.protocol.AbstractInvoker;\n-import org.apache.dubbo.rpc.support.RpcUtils;\n-\n-import java.util.Set;\n-import java.util.concurrent.CompletableFuture;\n-import java.util.concurrent.ExecutorService;\n-import java.util.concurrent.TimeUnit;\n-import java.util.concurrent.locks.ReentrantLock;\n-\n-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;\n-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_VERSION;\n-import static org.apache.dubbo.common.constants.CommonConstants.ENABLE_TIMEOUT_COUNTDOWN_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_ATTACHMENT_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.TIME_COUNTDOWN_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;\n-import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;\n-\n-/**\n- * DubboInvoker\n- */\n-public class DubboInvoker<T> extends AbstractInvoker<T> {\n-\n-    private final ExchangeClient[] clients;\n-\n-    private final AtomicPositiveInteger index = new AtomicPositiveInteger();\n-\n-    private final String version;\n-\n-    private final ReentrantLock destroyLock = new ReentrantLock();\n-\n-    private final Set<Invoker<?>> invokers;\n-\n-    public DubboInvoker(Class<T> serviceType, URL url, ExchangeClient[] clients) {\n-        this(serviceType, url, clients, null);\n-    }\n-\n-    public DubboInvoker(Class<T> serviceType, URL url, ExchangeClient[] clients, Set<Invoker<?>> invokers) {\n-        super(serviceType, url, new String[]{INTERFACE_KEY, GROUP_KEY, TOKEN_KEY});\n-        this.clients = clients;\n-        // get version.\n-        this.version = url.getParameter(VERSION_KEY, DEFAULT_VERSION);\n-        this.invokers = invokers;\n-    }\n-\n-    @Override\n-    protected Result doInvoke(final Invocation invocation) throws Throwable {\n-        RpcInvocation inv = (RpcInvocation) invocation;\n-        final String methodName = RpcUtils.getMethodName(invocation);\n-        inv.setAttachment(PATH_KEY, getUrl().getPath());\n-        inv.setAttachment(VERSION_KEY, version);\n-\n-        ExchangeClient currentClient;\n-        if (clients.length == 1) {\n-            currentClient = clients[0];\n-        } else {\n-            currentClient = clients[index.getAndIncrement() % clients.length];\n-        }\n-        try {\n-            boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);\n-            int timeout = calculateTimeout(invocation, methodName);\n-            invocation.put(TIMEOUT_KEY, timeout);\n-            if (isOneway) {\n-                boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);\n-                currentClient.send(inv, isSent);\n-                return AsyncRpcResult.newDefaultAsyncResult(invocation);\n-            } else {\n-                ExecutorService executor = getCallbackExecutor(getUrl(), inv);\n-                CompletableFuture<AppResponse> appResponseFuture =\n-                        currentClient.request(inv, timeout, executor).thenApply(obj -> (AppResponse) obj);\n-                // save for 2.6.x compatibility, for example, TraceFilter in Zipkin uses com.alibaba.xxx.FutureAdapter\n-                FutureContext.getContext().setCompatibleFuture(appResponseFuture);\n-                AsyncRpcResult result = new AsyncRpcResult(appResponseFuture, inv);\n-                result.setExecutor(executor);\n-                return result;\n-            }\n-        } catch (TimeoutException e) {\n-            throw new RpcException(RpcException.TIMEOUT_EXCEPTION, \"Invoke remote method timeout. method: \" + invocation.getMethodName() + \", provider: \" + getUrl() + \", cause: \" + e.getMessage(), e);\n-        } catch (RemotingException e) {\n-            throw new RpcException(RpcException.NETWORK_EXCEPTION, \"Failed to invoke remote method: \" + invocation.getMethodName() + \", provider: \" + getUrl() + \", cause: \" + e.getMessage(), e);\n-        }\n-    }\n-\n-    @Override\n-    public boolean isAvailable() {\n-        if (!super.isAvailable()) {\n-            return false;\n-        }\n-        for (ExchangeClient client : clients) {\n-            if (client.isConnected() && !client.hasAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY)) {\n-                //cannot write == not Available ?\n-                return true;\n-            }\n-        }\n-        return false;\n-    }\n-\n-    @Override\n-    public void destroy() {\n-        // in order to avoid closing a client multiple times, a counter is used in case of connection per jvm, every\n-        // time when client.close() is called, counter counts down once, and when counter reaches zero, client will be\n-        // closed.\n-        if (super.isDestroyed()) {\n-            return;\n-        } else {\n-            // double check to avoid dup close\n-            destroyLock.lock();\n-            try {\n-                if (super.isDestroyed()) {\n-                    return;\n-                }\n-                super.destroy();\n-                if (invokers != null) {\n-                    invokers.remove(this);\n-                }\n-                for (ExchangeClient client : clients) {\n-                    try {\n-                        client.close(ConfigurationUtils.getServerShutdownTimeout());\n-                    } catch (Throwable t) {\n-                        logger.warn(t.getMessage(), t);\n-                    }\n-                }\n-\n-            } finally {\n-                destroyLock.unlock();\n-            }\n-        }\n-    }\n-\n-    private int calculateTimeout(Invocation invocation, String methodName) {\n-        Object countdown = RpcContext.getContext().get(TIME_COUNTDOWN_KEY);\n-        int timeout = DEFAULT_TIMEOUT;\n-        if (countdown == null) {\n-            timeout = (int) RpcUtils.getTimeout(getUrl(), methodName, RpcContext.getContext(), DEFAULT_TIMEOUT);\n-            if (getUrl().getParameter(ENABLE_TIMEOUT_COUNTDOWN_KEY, false)) {\n-                invocation.setObjectAttachment(TIMEOUT_ATTACHMENT_KEY, timeout); // pass timeout to remote server\n-            }\n-        } else {\n-            TimeoutCountDown timeoutCountDown = (TimeoutCountDown) countdown;\n-            timeout = (int) timeoutCountDown.timeRemaining(TimeUnit.MILLISECONDS);\n-            invocation.setObjectAttachment(TIMEOUT_ATTACHMENT_KEY, timeout);// pass timeout to remote server\n-        }\n-        return timeout;\n-    }\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.common.config.ConfigurationUtils;\r\n+import org.apache.dubbo.common.utils.AtomicPositiveInteger;\r\n+import org.apache.dubbo.remoting.Constants;\r\n+import org.apache.dubbo.remoting.RemotingException;\r\n+import org.apache.dubbo.remoting.TimeoutException;\r\n+import org.apache.dubbo.remoting.exchange.ExchangeClient;\r\n+import org.apache.dubbo.rpc.AppResponse;\r\n+import org.apache.dubbo.rpc.AsyncRpcResult;\r\n+import org.apache.dubbo.rpc.FutureContext;\r\n+import org.apache.dubbo.rpc.Invocation;\r\n+import org.apache.dubbo.rpc.Invoker;\r\n+import org.apache.dubbo.rpc.Result;\r\n+import org.apache.dubbo.rpc.RpcContext;\r\n+import org.apache.dubbo.rpc.RpcException;\r\n+import org.apache.dubbo.rpc.RpcInvocation;\r\n+import org.apache.dubbo.rpc.TimeoutCountDown;\r\n+import org.apache.dubbo.rpc.protocol.AbstractInvoker;\r\n+import org.apache.dubbo.rpc.support.RpcUtils;\r\n+\r\n+import java.util.Set;\r\n+import java.util.concurrent.CompletableFuture;\r\n+import java.util.concurrent.ExecutorService;\r\n+import java.util.concurrent.TimeUnit;\r\n+import java.util.concurrent.locks.ReentrantLock;\r\n+\r\n+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_VERSION;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.ENABLE_TIMEOUT_COUNTDOWN_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_ATTACHMENT_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.TIME_COUNTDOWN_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;\r\n+import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;\r\n+\r\n+/**\r\n+ * DubboInvoker\r\n+ */\r\n+public class DubboInvoker<T> extends AbstractInvoker<T> {\r\n+\r\n+    private final ExchangeClient[] clients;\r\n+\r\n+    private final AtomicPositiveInteger index = new AtomicPositiveInteger();\r\n+\r\n+    private final String version;\r\n+\r\n+    private final ReentrantLock destroyLock = new ReentrantLock();\r\n+\r\n+    private final Set<Invoker<?>> invokers;\r\n+\r\n+    public DubboInvoker(Class<T> serviceType, URL url, ExchangeClient[] clients) {\r\n+        this(serviceType, url, clients, null);\r\n+    }\r\n+\r\n+    public DubboInvoker(Class<T> serviceType, URL url, ExchangeClient[] clients, Set<Invoker<?>> invokers) {\r\n+        super(serviceType, url, new String[]{INTERFACE_KEY, GROUP_KEY, TOKEN_KEY});\r\n+        this.clients = clients;\r\n+        // get version.\r\n+        this.version = url.getParameter(VERSION_KEY, DEFAULT_VERSION);\r\n+        this.invokers = invokers;\r\n+    }\r\n+\r\n+    @Override\r\n+    protected Result doInvoke(final Invocation invocation) throws Throwable {\r\n+        RpcInvocation inv = (RpcInvocation) invocation;\r\n+        final String methodName = RpcUtils.getMethodName(invocation);\r\n+        inv.setAttachment(PATH_KEY, getUrl().getPath());\r\n+        inv.setAttachment(VERSION_KEY, version);\r\n+\r\n+        ExchangeClient currentClient;\r\n+        if (clients.length == 1) {\r\n+            currentClient = clients[0];\r\n+        } else {\r\n+            currentClient = clients[index.getAndIncrement() % clients.length];\r\n+        }\r\n+        try {\r\n+            boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);\r\n+            int timeout = calculateTimeout(invocation, methodName);\r\n+            invocation.put(TIMEOUT_KEY, timeout);\r\n+            if (isOneway) {\r\n+                boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);\r\n+                currentClient.send(inv, isSent);\r\n+                return AsyncRpcResult.newDefaultAsyncResult(invocation);\r\n+            } else {\r\n+                ExecutorService executor = getCallbackExecutor(getUrl(), inv);\r\n+                CompletableFuture<AppResponse> appResponseFuture =\r\n+                        currentClient.request(inv, timeout, executor).thenApply(obj -> (AppResponse) obj);\r\n+                // save for 2.6.x compatibility, for example, TraceFilter in Zipkin uses com.alibaba.xxx.FutureAdapter\r\n+                FutureContext.getContext().setCompatibleFuture(appResponseFuture);\r\n+                AsyncRpcResult result = new AsyncRpcResult(appResponseFuture, inv);\r\n+                result.setExecutor(executor);\r\n+                return result;\r\n+            }\r\n+        } catch (TimeoutException e) {\r\n+            throw new RpcException(RpcException.TIMEOUT_EXCEPTION, \"Invoke remote method timeout. method: \" + invocation.getMethodName() + \", provider: \" + getUrl() + \", cause: \" + e.getMessage(), e);\r\n+        } catch (RemotingException e) {\r\n+            throw new RpcException(RpcException.NETWORK_EXCEPTION, \"Failed to invoke remote method: \" + invocation.getMethodName() + \", provider: \" + getUrl() + \", cause: \" + e.getMessage(), e);\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean isAvailable() {\r\n+        if (!super.isAvailable()) {\r\n+            return false;\r\n+        }\r\n+        for (ExchangeClient client : clients) {\r\n+            if (client.isConnected() && !client.hasAttribute(Constants.CHANNEL_ATTRIBUTE_READONLY_KEY)) {\r\n+                //cannot write == not Available ?\r\n+                return true;\r\n+            }\r\n+        }\r\n+        return false;\r\n+    }\r\n+\r\n+    @Override\r\n+    public void destroy() {\r\n+        // in order to avoid closing a client multiple times, a counter is used in case of connection per jvm, every\r\n+        // time when client.close() is called, counter counts down once, and when counter reaches zero, client will be\r\n+        // closed.\r\n+        if (super.isDestroyed()) {\r\n+            return;\r\n+        } else {\r\n+            // double check to avoid dup close\r\n+            destroyLock.lock();\r\n+            try {\r\n+                if (super.isDestroyed()) {\r\n+                    return;\r\n+                }\r\n+                super.destroy();\r\n+                if (invokers != null) {\r\n+                    invokers.remove(this);\r\n+                }\r\n+                for (ExchangeClient client : clients) {\r\n+                    try {\r\n+                        client.close(ConfigurationUtils.getServerShutdownTimeout());\r\n+                    } catch (Throwable t) {\r\n+                        logger.warn(t.getMessage(), t);\r\n+                    }\r\n+                }\r\n+\r\n+            } finally {\r\n+                destroyLock.unlock();\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+    private int calculateTimeout(Invocation invocation, String methodName) {\r\n+        Object countdown = RpcContext.getContext().get(TIME_COUNTDOWN_KEY);\r\n+        int timeout = DEFAULT_TIMEOUT;\r\n+        if (countdown == null) {\r\n+            timeout = (int) RpcUtils.getTimeout(getUrl(), methodName, RpcContext.getContext(), DEFAULT_TIMEOUT);\r\n+            if (getUrl().getParameter(ENABLE_TIMEOUT_COUNTDOWN_KEY, false)) {\r\n+                invocation.setObjectAttachment(TIMEOUT_ATTACHMENT_KEY, timeout); // pass timeout to remote server\r\n+            }\r\n+        } else {\r\n+            TimeoutCountDown timeoutCountDown = (TimeoutCountDown) countdown;\r\n+            timeout = (int) timeoutCountDown.timeRemaining(TimeUnit.MILLISECONDS);\r\n+            invocation.setObjectAttachment(TIMEOUT_ATTACHMENT_KEY, timeout);// pass timeout to remote server\r\n+        }\r\n+        return timeout;\r\n+    }\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,686 +1,686 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.common.URLBuilder;\n-import org.apache.dubbo.common.config.ConfigurationUtils;\n-import org.apache.dubbo.common.extension.ExtensionLoader;\n-import org.apache.dubbo.common.serialize.support.SerializableClassRegistry;\n-import org.apache.dubbo.common.serialize.support.SerializationOptimizer;\n-import org.apache.dubbo.common.utils.CollectionUtils;\n-import org.apache.dubbo.common.utils.ConcurrentHashSet;\n-import org.apache.dubbo.common.utils.ConfigUtils;\n-import org.apache.dubbo.common.utils.NetUtils;\n-import org.apache.dubbo.common.utils.StringUtils;\n-import org.apache.dubbo.remoting.Channel;\n-import org.apache.dubbo.remoting.RemotingException;\n-import org.apache.dubbo.remoting.RemotingServer;\n-import org.apache.dubbo.remoting.Transporter;\n-import org.apache.dubbo.remoting.exchange.ExchangeChannel;\n-import org.apache.dubbo.remoting.exchange.ExchangeClient;\n-import org.apache.dubbo.remoting.exchange.ExchangeHandler;\n-import org.apache.dubbo.remoting.exchange.ExchangeServer;\n-import org.apache.dubbo.remoting.exchange.Exchangers;\n-import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerAdapter;\n-import org.apache.dubbo.rpc.Exporter;\n-import org.apache.dubbo.rpc.Invocation;\n-import org.apache.dubbo.rpc.Invoker;\n-import org.apache.dubbo.rpc.Protocol;\n-import org.apache.dubbo.rpc.ProtocolServer;\n-import org.apache.dubbo.rpc.Result;\n-import org.apache.dubbo.rpc.RpcContext;\n-import org.apache.dubbo.rpc.RpcException;\n-import org.apache.dubbo.rpc.RpcInvocation;\n-import org.apache.dubbo.rpc.protocol.AbstractProtocol;\n-\n-import java.net.InetSocketAddress;\n-import java.util.ArrayList;\n-import java.util.Collection;\n-import java.util.Collections;\n-import java.util.List;\n-import java.util.Map;\n-import java.util.Set;\n-import java.util.concurrent.CompletableFuture;\n-import java.util.concurrent.ConcurrentHashMap;\n-import java.util.concurrent.ConcurrentMap;\n-import java.util.function.Function;\n-\n-import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.LAZY_CONNECT_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.STUB_EVENT_KEY;\n-import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;\n-import static org.apache.dubbo.remoting.Constants.CHANNEL_READONLYEVENT_SENT_KEY;\n-import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;\n-import static org.apache.dubbo.remoting.Constants.CODEC_KEY;\n-import static org.apache.dubbo.remoting.Constants.CONNECTIONS_KEY;\n-import static org.apache.dubbo.remoting.Constants.DEFAULT_HEARTBEAT;\n-import static org.apache.dubbo.remoting.Constants.DEFAULT_REMOTING_CLIENT;\n-import static org.apache.dubbo.remoting.Constants.HEARTBEAT_KEY;\n-import static org.apache.dubbo.remoting.Constants.SERVER_KEY;\n-import static org.apache.dubbo.rpc.Constants.DEFAULT_REMOTING_SERVER;\n-import static org.apache.dubbo.rpc.Constants.DEFAULT_STUB_EVENT;\n-import static org.apache.dubbo.rpc.Constants.IS_SERVER_KEY;\n-import static org.apache.dubbo.rpc.Constants.STUB_EVENT_METHODS_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.DEFAULT_SHARE_CONNECTIONS;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.IS_CALLBACK_SERVICE;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.ON_CONNECT_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.ON_DISCONNECT_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.OPTIMIZER_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.SHARE_CONNECTIONS_KEY;\n-\n-\n-/**\n- * dubbo protocol support.\n- */\n-public class DubboProtocol extends AbstractProtocol {\n-\n-    public static final String NAME = \"dubbo\";\n-\n-    public static final int DEFAULT_PORT = 20880;\n-    private static final String IS_CALLBACK_SERVICE_INVOKE = \"_isCallBackServiceInvoke\";\n-    private static DubboProtocol INSTANCE;\n-\n-    /**\n-     * <host:port,Exchanger>\n-     */\n-    private final Map<String, List<ReferenceCountExchangeClient>> referenceClientMap = new ConcurrentHashMap<>();\n-    private final ConcurrentMap<String, Object> locks = new ConcurrentHashMap<>();\n-    private final Set<String> optimizers = new ConcurrentHashSet<>();\n-\n-    private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() {\n-\n-        @Override\n-        public CompletableFuture<Object> reply(ExchangeChannel channel, Object message) throws RemotingException {\n-\n-            if (!(message instanceof Invocation)) {\n-                throw new RemotingException(channel, \"Unsupported request: \"\n-                        + (message == null ? null : (message.getClass().getName() + \": \" + message))\n-                        + \", channel: consumer: \" + channel.getRemoteAddress() + \" --> provider: \" + channel.getLocalAddress());\n-            }\n-\n-            Invocation inv = (Invocation) message;\n-            Invoker<?> invoker = getInvoker(channel, inv);\n-            // need to consider backward-compatibility if it's a callback\n-            if (Boolean.TRUE.toString().equals(inv.getObjectAttachments().get(IS_CALLBACK_SERVICE_INVOKE))) {\n-                String methodsStr = invoker.getUrl().getParameters().get(\"methods\");\n-                boolean hasMethod = false;\n-                if (methodsStr == null || !methodsStr.contains(\",\")) {\n-                    hasMethod = inv.getMethodName().equals(methodsStr);\n-                } else {\n-                    String[] methods = methodsStr.split(\",\");\n-                    for (String method : methods) {\n-                        if (inv.getMethodName().equals(method)) {\n-                            hasMethod = true;\n-                            break;\n-                        }\n-                    }\n-                }\n-                if (!hasMethod) {\n-                    logger.warn(new IllegalStateException(\"The methodName \" + inv.getMethodName()\n-                            + \" not found in callback service interface ,invoke will be ignored.\"\n-                            + \" please update the api interface. url is:\"\n-                            + invoker.getUrl()) + \" ,invocation is :\" + inv);\n-                    return null;\n-                }\n-            }\n-            RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());\n-            Result result = invoker.invoke(inv);\n-            return result.thenApply(Function.identity());\n-        }\n-\n-        @Override\n-        public void received(Channel channel, Object message) throws RemotingException {\n-            if (message instanceof Invocation) {\n-                reply((ExchangeChannel) channel, message);\n-\n-            } else {\n-                super.received(channel, message);\n-            }\n-        }\n-\n-        @Override\n-        public void connected(Channel channel) throws RemotingException {\n-            invoke(channel, ON_CONNECT_KEY);\n-        }\n-\n-        @Override\n-        public void disconnected(Channel channel) throws RemotingException {\n-            if (logger.isDebugEnabled()) {\n-                logger.debug(\"disconnected from \" + channel.getRemoteAddress() + \",url:\" + channel.getUrl());\n-            }\n-            invoke(channel, ON_DISCONNECT_KEY);\n-        }\n-\n-        private void invoke(Channel channel, String methodKey) {\n-            Invocation invocation = createInvocation(channel, channel.getUrl(), methodKey);\n-            if (invocation != null) {\n-                try {\n-                    received(channel, invocation);\n-                } catch (Throwable t) {\n-                    logger.warn(\"Failed to invoke event method \" + invocation.getMethodName() + \"(), cause: \" + t.getMessage(), t);\n-                }\n-            }\n-        }\n-\n-        /**\n-         * FIXME channel.getUrl() always binds to a fixed service, and this service is random.\n-         * we can choose to use a common service to carry onConnect event if there's no easy way to get the specific\n-         * service this connection is binding to.\n-         * @param channel\n-         * @param url\n-         * @param methodKey\n-         * @return\n-         */\n-        private Invocation createInvocation(Channel channel, URL url, String methodKey) {\n-            String method = url.getParameter(methodKey);\n-            if (method == null || method.length() == 0) {\n-                return null;\n-            }\n-\n-            RpcInvocation invocation = new RpcInvocation(method, url.getParameter(INTERFACE_KEY), \"\", new Class<?>[0], new Object[0]);\n-            invocation.setAttachment(PATH_KEY, url.getPath());\n-            invocation.setAttachment(GROUP_KEY, url.getParameter(GROUP_KEY));\n-            invocation.setAttachment(INTERFACE_KEY, url.getParameter(INTERFACE_KEY));\n-            invocation.setAttachment(VERSION_KEY, url.getParameter(VERSION_KEY));\n-            if (url.getParameter(STUB_EVENT_KEY, false)) {\n-                invocation.setAttachment(STUB_EVENT_KEY, Boolean.TRUE.toString());\n-            }\n-\n-            return invocation;\n-        }\n-    };\n-\n-    public DubboProtocol() {\n-        INSTANCE = this;\n-    }\n-\n-    public static DubboProtocol getDubboProtocol() {\n-        if (INSTANCE == null) {\n-            // load\n-            ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(DubboProtocol.NAME);\n-        }\n-\n-        return INSTANCE;\n-    }\n-\n-    @Override\n-    public Collection<Exporter<?>> getExporters() {\n-        return Collections.unmodifiableCollection(exporterMap.values());\n-    }\n-\n-    private boolean isClientSide(Channel channel) {\n-        InetSocketAddress address = channel.getRemoteAddress();\n-        URL url = channel.getUrl();\n-        return url.getPort() == address.getPort() &&\n-                NetUtils.filterLocalHost(channel.getUrl().getIp())\n-                        .equals(NetUtils.filterLocalHost(address.getAddress().getHostAddress()));\n-    }\n-\n-    Invoker<?> getInvoker(Channel channel, Invocation inv) throws RemotingException {\n-        boolean isCallBackServiceInvoke = false;\n-        boolean isStubServiceInvoke = false;\n-        int port = channel.getLocalAddress().getPort();\n-        String path = (String) inv.getObjectAttachments().get(PATH_KEY);\n-\n-        // if it's callback service on client side\n-        isStubServiceInvoke = Boolean.TRUE.toString().equals(inv.getObjectAttachments().get(STUB_EVENT_KEY));\n-        if (isStubServiceInvoke) {\n-            port = channel.getRemoteAddress().getPort();\n-        }\n-\n-        //callback\n-        isCallBackServiceInvoke = isClientSide(channel) && !isStubServiceInvoke;\n-        if (isCallBackServiceInvoke) {\n-            path += \".\" + inv.getObjectAttachments().get(CALLBACK_SERVICE_KEY);\n-            inv.getObjectAttachments().put(IS_CALLBACK_SERVICE_INVOKE, Boolean.TRUE.toString());\n-        }\n-\n-        String serviceKey = serviceKey(\n-                port,\n-                path,\n-                (String) inv.getObjectAttachments().get(VERSION_KEY),\n-                (String) inv.getObjectAttachments().get(GROUP_KEY)\n-        );\n-        DubboExporter<?> exporter = (DubboExporter<?>) exporterMap.get(serviceKey);\n-\n-        if (exporter == null) {\n-            throw new RemotingException(channel, \"Not found exported service: \" + serviceKey + \" in \" + exporterMap.keySet() + \", may be version or group mismatch \" +\n-                    \", channel: consumer: \" + channel.getRemoteAddress() + \" --> provider: \" + channel.getLocalAddress() + \", message:\" + getInvocationWithoutData(inv));\n-        }\n-\n-        return exporter.getInvoker();\n-    }\n-\n-    public Collection<Invoker<?>> getInvokers() {\n-        return Collections.unmodifiableCollection(invokers);\n-    }\n-\n-    @Override\n-    public int getDefaultPort() {\n-        return DEFAULT_PORT;\n-    }\n-\n-    @Override\n-    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {\n-        URL url = invoker.getUrl();\n-\n-        // export service.\n-        String key = serviceKey(url);\n-        DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);\n-        exporterMap.put(key, exporter);\n-\n-        //export an stub service for dispatching event\n-        Boolean isStubSupportEvent = url.getParameter(STUB_EVENT_KEY, DEFAULT_STUB_EVENT);\n-        Boolean isCallbackservice = url.getParameter(IS_CALLBACK_SERVICE, false);\n-        if (isStubSupportEvent && !isCallbackservice) {\n-            String stubServiceMethods = url.getParameter(STUB_EVENT_METHODS_KEY);\n-            if (stubServiceMethods == null || stubServiceMethods.length() == 0) {\n-                if (logger.isWarnEnabled()) {\n-                    logger.warn(new IllegalStateException(\"consumer [\" + url.getParameter(INTERFACE_KEY) +\n-                            \"], has set stubproxy support event ,but no stub methods founded.\"));\n-                }\n-\n-            }\n-        }\n-\n-        openServer(url);\n-        optimizeSerialization(url);\n-\n-        return exporter;\n-    }\n-\n-    private void openServer(URL url) {\n-        // find server.\n-        String key = url.getAddress();\n-        //client can export a service which's only for server to invoke\n-        boolean isServer = url.getParameter(IS_SERVER_KEY, true);\n-        if (isServer) {\n-            ProtocolServer server = serverMap.get(key);\n-            if (server == null) {\n-                synchronized (this) {\n-                    server = serverMap.get(key);\n-                    if (server == null) {\n-                        serverMap.put(key, createServer(url));\n-                    }\n-                }\n-            } else {\n-                // server supports reset, use together with override\n-                server.reset(url);\n-            }\n-        }\n-    }\n-\n-    private ProtocolServer createServer(URL url) {\n-        url = URLBuilder.from(url)\n-                // send readonly event when server closes, it's enabled by default\n-                .addParameterIfAbsent(CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString())\n-                // enable heartbeat by default\n-                .addParameterIfAbsent(HEARTBEAT_KEY, String.valueOf(DEFAULT_HEARTBEAT))\n-                .addParameter(CODEC_KEY, DubboCodec.NAME)\n-                .build();\n-        String str = url.getParameter(SERVER_KEY, DEFAULT_REMOTING_SERVER);\n-\n-        if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str)) {\n-            throw new RpcException(\"Unsupported server type: \" + str + \", url: \" + url);\n-        }\n-\n-        ExchangeServer server;\n-        try {\n-            server = Exchangers.bind(url, requestHandler);\n-        } catch (RemotingException e) {\n-            throw new RpcException(\"Fail to start server(url: \" + url + \") \" + e.getMessage(), e);\n-        }\n-\n-        str = url.getParameter(CLIENT_KEY);\n-        if (str != null && str.length() > 0) {\n-            Set<String> supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions();\n-            if (!supportedTypes.contains(str)) {\n-                throw new RpcException(\"Unsupported client type: \" + str);\n-            }\n-        }\n-\n-        return new DubboProtocolServer(server);\n-    }\n-\n-    private void optimizeSerialization(URL url) throws RpcException {\n-        String className = url.getParameter(OPTIMIZER_KEY, \"\");\n-        if (StringUtils.isEmpty(className) || optimizers.contains(className)) {\n-            return;\n-        }\n-\n-        logger.info(\"Optimizing the serialization process for Kryo, FST, etc...\");\n-\n-        try {\n-            Class clazz = Thread.currentThread().getContextClassLoader().loadClass(className);\n-            if (!SerializationOptimizer.class.isAssignableFrom(clazz)) {\n-                throw new RpcException(\"The serialization optimizer \" + className + \" isn't an instance of \" + SerializationOptimizer.class.getName());\n-            }\n-\n-            SerializationOptimizer optimizer = (SerializationOptimizer) clazz.newInstance();\n-\n-            if (optimizer.getSerializableClasses() == null) {\n-                return;\n-            }\n-\n-            for (Class c : optimizer.getSerializableClasses()) {\n-                SerializableClassRegistry.registerClass(c);\n-            }\n-\n-            optimizers.add(className);\n-\n-        } catch (ClassNotFoundException e) {\n-            throw new RpcException(\"Cannot find the serialization optimizer class: \" + className, e);\n-\n-        } catch (InstantiationException | IllegalAccessException e) {\n-            throw new RpcException(\"Cannot instantiate the serialization optimizer class: \" + className, e);\n-\n-        }\n-    }\n-\n-    @Override\n-    public <T> Invoker<T> protocolBindingRefer(Class<T> serviceType, URL url) throws RpcException {\n-        optimizeSerialization(url);\n-\n-        // create rpc invoker.\n-        DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);\n-        invokers.add(invoker);\n-\n-        return invoker;\n-    }\n-\n-    private ExchangeClient[] getClients(URL url) {\n-        // whether to share connection\n-\n-        boolean useShareConnect = false;\n-\n-        int connections = url.getParameter(CONNECTIONS_KEY, 0);\n-        List<ReferenceCountExchangeClient> shareClients = null;\n-        // if not configured, connection is shared, otherwise, one connection for one service\n-        if (connections == 0) {\n-            useShareConnect = true;\n-\n-            /*\n-             * The xml configuration should have a higher priority than properties.\n-             */\n-            String shareConnectionsStr = url.getParameter(SHARE_CONNECTIONS_KEY, (String) null);\n-            connections = Integer.parseInt(StringUtils.isBlank(shareConnectionsStr) ? ConfigUtils.getProperty(SHARE_CONNECTIONS_KEY,\n-                    DEFAULT_SHARE_CONNECTIONS) : shareConnectionsStr);\n-            shareClients = getSharedClient(url, connections);\n-        }\n-\n-        ExchangeClient[] clients = new ExchangeClient[connections];\n-        for (int i = 0; i < clients.length; i++) {\n-            if (useShareConnect) {\n-                clients[i] = shareClients.get(i);\n-\n-            } else {\n-                clients[i] = initClient(url);\n-            }\n-        }\n-\n-        return clients;\n-    }\n-\n-    /**\n-     * Get shared connection\n-     *\n-     * @param url\n-     * @param connectNum connectNum must be greater than or equal to 1\n-     */\n-    private List<ReferenceCountExchangeClient> getSharedClient(URL url, int connectNum) {\n-        String key = url.getAddress();\n-        List<ReferenceCountExchangeClient> clients = referenceClientMap.get(key);\n-\n-        if (checkClientCanUse(clients)) {\n-            batchClientRefIncr(clients);\n-            return clients;\n-        }\n-\n-        locks.putIfAbsent(key, new Object());\n-        synchronized (locks.get(key)) {\n-            clients = referenceClientMap.get(key);\n-            // double check\n-            if (checkClientCanUse(clients)) {\n-                batchClientRefIncr(clients);\n-                return clients;\n-            }\n-\n-            // connectNum must be greater than or equal to 1\n-            connectNum = Math.max(connectNum, 1);\n-\n-            // If the clients is empty, then the first initialization is\n-            if (CollectionUtils.isEmpty(clients)) {\n-                clients = buildReferenceCountExchangeClientList(url, connectNum);\n-                referenceClientMap.put(key, clients);\n-\n-            } else {\n-                for (int i = 0; i < clients.size(); i++) {\n-                    ReferenceCountExchangeClient referenceCountExchangeClient = clients.get(i);\n-                    // If there is a client in the list that is no longer available, create a new one to replace him.\n-                    if (referenceCountExchangeClient == null || referenceCountExchangeClient.isClosed()) {\n-                        clients.set(i, buildReferenceCountExchangeClient(url));\n-                        continue;\n-                    }\n-\n-                    referenceCountExchangeClient.incrementAndGetCount();\n-                }\n-            }\n-\n-            /*\n-             * I understand that the purpose of the remove operation here is to avoid the expired url key\n-             * always occupying this memory space.\n-             * But \"locks.remove(key);\" can lead to \"synchronized (locks.get(key)) {\" NPE, considering that the key of locks is \"IP + port\",\n-             * it will not lead to the expansion of \"locks\" in theory, so I will annotate it here.\n-             */\n-//            locks.remove(key);\n-\n-            return clients;\n-        }\n-    }\n-\n-    /**\n-     * Check if the client list is all available\n-     *\n-     * @param referenceCountExchangeClients\n-     * @return true-available\uff0cfalse-unavailable\n-     */\n-    private boolean checkClientCanUse(List<ReferenceCountExchangeClient> referenceCountExchangeClients) {\n-        if (CollectionUtils.isEmpty(referenceCountExchangeClients)) {\n-            return false;\n-        }\n-\n-        for (ReferenceCountExchangeClient referenceCountExchangeClient : referenceCountExchangeClients) {\n-            // As long as one client is not available, you need to replace the unavailable client with the available one.\n-            if (referenceCountExchangeClient == null || referenceCountExchangeClient.getCount() <= 0 || referenceCountExchangeClient.isClosed()) {\n-                return false;\n-            }\n-        }\n-\n-        return true;\n-    }\n-\n-    /**\n-     * Increase the reference Count if we create new invoker shares same connection, the connection will be closed without any reference.\n-     *\n-     * @param referenceCountExchangeClients\n-     */\n-    private void batchClientRefIncr(List<ReferenceCountExchangeClient> referenceCountExchangeClients) {\n-        if (CollectionUtils.isEmpty(referenceCountExchangeClients)) {\n-            return;\n-        }\n-\n-        for (ReferenceCountExchangeClient referenceCountExchangeClient : referenceCountExchangeClients) {\n-            if (referenceCountExchangeClient != null) {\n-                referenceCountExchangeClient.incrementAndGetCount();\n-            }\n-        }\n-    }\n-\n-    /**\n-     * Bulk build client\n-     *\n-     * @param url\n-     * @param connectNum\n-     * @return\n-     */\n-    private List<ReferenceCountExchangeClient> buildReferenceCountExchangeClientList(URL url, int connectNum) {\n-        List<ReferenceCountExchangeClient> clients = new ArrayList<>();\n-\n-        for (int i = 0; i < connectNum; i++) {\n-            clients.add(buildReferenceCountExchangeClient(url));\n-        }\n-\n-        return clients;\n-    }\n-\n-    /**\n-     * Build a single client\n-     *\n-     * @param url\n-     * @return\n-     */\n-    private ReferenceCountExchangeClient buildReferenceCountExchangeClient(URL url) {\n-        ExchangeClient exchangeClient = initClient(url);\n-\n-        return new ReferenceCountExchangeClient(exchangeClient);\n-    }\n-\n-    /**\n-     * Create new connection\n-     *\n-     * @param url\n-     */\n-    private ExchangeClient initClient(URL url) {\n-\n-        // client type setting.\n-        String str = url.getParameter(CLIENT_KEY, url.getParameter(SERVER_KEY, DEFAULT_REMOTING_CLIENT));\n-\n-        url = url.addParameter(CODEC_KEY, DubboCodec.NAME);\n-        // enable heartbeat by default\n-        url = url.addParameterIfAbsent(HEARTBEAT_KEY, String.valueOf(DEFAULT_HEARTBEAT));\n-\n-        // BIO is not allowed since it has severe performance issue.\n-        if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str)) {\n-            throw new RpcException(\"Unsupported client type: \" + str + \",\" +\n-                    \" supported client type is \" + StringUtils.join(ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions(), \" \"));\n-        }\n-\n-        ExchangeClient client;\n-        try {\n-            // connection should be lazy\n-            if (url.getParameter(LAZY_CONNECT_KEY, false)) {\n-                client = new LazyConnectExchangeClient(url, requestHandler);\n-\n-            } else {\n-                client = Exchangers.connect(url, requestHandler);\n-            }\n-\n-        } catch (RemotingException e) {\n-            throw new RpcException(\"Fail to create remoting client for service(\" + url + \"): \" + e.getMessage(), e);\n-        }\n-\n-        return client;\n-    }\n-\n-    @Override\n-    public void destroy() {\n-        for (String key : new ArrayList<>(serverMap.keySet())) {\n-            ProtocolServer protocolServer = serverMap.remove(key);\n-\n-            if (protocolServer == null) {\n-                continue;\n-            }\n-\n-            RemotingServer server = protocolServer.getRemotingServer();\n-\n-            try {\n-                if (logger.isInfoEnabled()) {\n-                    logger.info(\"Close dubbo server: \" + server.getLocalAddress());\n-                }\n-\n-                server.close(ConfigurationUtils.getServerShutdownTimeout());\n-\n-            } catch (Throwable t) {\n-                logger.warn(t.getMessage(), t);\n-            }\n-        }\n-\n-        for (String key : new ArrayList<>(referenceClientMap.keySet())) {\n-            List<ReferenceCountExchangeClient> clients = referenceClientMap.remove(key);\n-\n-            if (CollectionUtils.isEmpty(clients)) {\n-                continue;\n-            }\n-\n-            for (ReferenceCountExchangeClient client : clients) {\n-                closeReferenceCountExchangeClient(client);\n-            }\n-        }\n-\n-        super.destroy();\n-    }\n-\n-    /**\n-     * close ReferenceCountExchangeClient\n-     *\n-     * @param client\n-     */\n-    private void closeReferenceCountExchangeClient(ReferenceCountExchangeClient client) {\n-        if (client == null) {\n-            return;\n-        }\n-\n-        try {\n-            if (logger.isInfoEnabled()) {\n-                logger.info(\"Close dubbo connect: \" + client.getLocalAddress() + \"-->\" + client.getRemoteAddress());\n-            }\n-\n-            client.close(ConfigurationUtils.getServerShutdownTimeout());\n-\n-            // TODO\n-            /*\n-             * At this time, ReferenceCountExchangeClient#client has been replaced with LazyConnectExchangeClient.\n-             * Do you need to call client.close again to ensure that LazyConnectExchangeClient is also closed?\n-             */\n-\n-        } catch (Throwable t) {\n-            logger.warn(t.getMessage(), t);\n-        }\n-    }\n-\n-    /**\n-     * only log body in debugger mode for size & security consideration.\n-     *\n-     * @param invocation\n-     * @return\n-     */\n-    private Invocation getInvocationWithoutData(Invocation invocation) {\n-        if (logger.isDebugEnabled()) {\n-            return invocation;\n-        }\n-        if (invocation instanceof RpcInvocation) {\n-            RpcInvocation rpcInvocation = (RpcInvocation) invocation;\n-            rpcInvocation.setArguments(null);\n-            return rpcInvocation;\n-        }\n-        return invocation;\n-    }\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.common.URLBuilder;\r\n+import org.apache.dubbo.common.config.ConfigurationUtils;\r\n+import org.apache.dubbo.common.extension.ExtensionLoader;\r\n+import org.apache.dubbo.common.serialize.support.SerializableClassRegistry;\r\n+import org.apache.dubbo.common.serialize.support.SerializationOptimizer;\r\n+import org.apache.dubbo.common.utils.CollectionUtils;\r\n+import org.apache.dubbo.common.utils.ConcurrentHashSet;\r\n+import org.apache.dubbo.common.utils.ConfigUtils;\r\n+import org.apache.dubbo.common.utils.NetUtils;\r\n+import org.apache.dubbo.common.utils.StringUtils;\r\n+import org.apache.dubbo.remoting.Channel;\r\n+import org.apache.dubbo.remoting.RemotingException;\r\n+import org.apache.dubbo.remoting.RemotingServer;\r\n+import org.apache.dubbo.remoting.Transporter;\r\n+import org.apache.dubbo.remoting.exchange.ExchangeChannel;\r\n+import org.apache.dubbo.remoting.exchange.ExchangeClient;\r\n+import org.apache.dubbo.remoting.exchange.ExchangeHandler;\r\n+import org.apache.dubbo.remoting.exchange.ExchangeServer;\r\n+import org.apache.dubbo.remoting.exchange.Exchangers;\r\n+import org.apache.dubbo.remoting.exchange.support.ExchangeHandlerAdapter;\r\n+import org.apache.dubbo.rpc.Exporter;\r\n+import org.apache.dubbo.rpc.Invocation;\r\n+import org.apache.dubbo.rpc.Invoker;\r\n+import org.apache.dubbo.rpc.Protocol;\r\n+import org.apache.dubbo.rpc.ProtocolServer;\r\n+import org.apache.dubbo.rpc.Result;\r\n+import org.apache.dubbo.rpc.RpcContext;\r\n+import org.apache.dubbo.rpc.RpcException;\r\n+import org.apache.dubbo.rpc.RpcInvocation;\r\n+import org.apache.dubbo.rpc.protocol.AbstractProtocol;\r\n+\r\n+import java.net.InetSocketAddress;\r\n+import java.util.ArrayList;\r\n+import java.util.Collection;\r\n+import java.util.Collections;\r\n+import java.util.List;\r\n+import java.util.Map;\r\n+import java.util.Set;\r\n+import java.util.concurrent.CompletableFuture;\r\n+import java.util.concurrent.ConcurrentHashMap;\r\n+import java.util.concurrent.ConcurrentMap;\r\n+import java.util.function.Function;\r\n+\r\n+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.LAZY_CONNECT_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.STUB_EVENT_KEY;\r\n+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;\r\n+import static org.apache.dubbo.remoting.Constants.CHANNEL_READONLYEVENT_SENT_KEY;\r\n+import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;\r\n+import static org.apache.dubbo.remoting.Constants.CODEC_KEY;\r\n+import static org.apache.dubbo.remoting.Constants.CONNECTIONS_KEY;\r\n+import static org.apache.dubbo.remoting.Constants.DEFAULT_HEARTBEAT;\r\n+import static org.apache.dubbo.remoting.Constants.DEFAULT_REMOTING_CLIENT;\r\n+import static org.apache.dubbo.remoting.Constants.HEARTBEAT_KEY;\r\n+import static org.apache.dubbo.remoting.Constants.SERVER_KEY;\r\n+import static org.apache.dubbo.rpc.Constants.DEFAULT_REMOTING_SERVER;\r\n+import static org.apache.dubbo.rpc.Constants.DEFAULT_STUB_EVENT;\r\n+import static org.apache.dubbo.rpc.Constants.IS_SERVER_KEY;\r\n+import static org.apache.dubbo.rpc.Constants.STUB_EVENT_METHODS_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.DEFAULT_SHARE_CONNECTIONS;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.IS_CALLBACK_SERVICE;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.ON_CONNECT_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.ON_DISCONNECT_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.OPTIMIZER_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.SHARE_CONNECTIONS_KEY;\r\n+\r\n+\r\n+/**\r\n+ * dubbo protocol support.\r\n+ */\r\n+public class DubboProtocol extends AbstractProtocol {\r\n+\r\n+    public static final String NAME = \"dubbo\";\r\n+\r\n+    public static final int DEFAULT_PORT = 20880;\r\n+    private static final String IS_CALLBACK_SERVICE_INVOKE = \"_isCallBackServiceInvoke\";\r\n+    private static DubboProtocol INSTANCE;\r\n+\r\n+    /**\r\n+     * <host:port,Exchanger>\r\n+     */\r\n+    private final Map<String, List<ReferenceCountExchangeClient>> referenceClientMap = new ConcurrentHashMap<>();\r\n+    private final ConcurrentMap<String, Object> locks = new ConcurrentHashMap<>();\r\n+    private final Set<String> optimizers = new ConcurrentHashSet<>();\r\n+\r\n+    private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() {\r\n+\r\n+        @Override\r\n+        public CompletableFuture<Object> reply(ExchangeChannel channel, Object message) throws RemotingException {\r\n+\r\n+            if (!(message instanceof Invocation)) {\r\n+                throw new RemotingException(channel, \"Unsupported request: \"\r\n+                        + (message == null ? null : (message.getClass().getName() + \": \" + message))\r\n+                        + \", channel: consumer: \" + channel.getRemoteAddress() + \" --> provider: \" + channel.getLocalAddress());\r\n+            }\r\n+\r\n+            Invocation inv = (Invocation) message;\r\n+            Invoker<?> invoker = getInvoker(channel, inv);\r\n+            // need to consider backward-compatibility if it's a callback\r\n+            if (Boolean.TRUE.toString().equals(inv.getObjectAttachments().get(IS_CALLBACK_SERVICE_INVOKE))) {\r\n+                String methodsStr = invoker.getUrl().getParameters().get(\"methods\");\r\n+                boolean hasMethod = false;\r\n+                if (methodsStr == null || !methodsStr.contains(\",\")) {\r\n+                    hasMethod = inv.getMethodName().equals(methodsStr);\r\n+                } else {\r\n+                    String[] methods = methodsStr.split(\",\");\r\n+                    for (String method : methods) {\r\n+                        if (inv.getMethodName().equals(method)) {\r\n+                            hasMethod = true;\r\n+                            break;\r\n+                        }\r\n+                    }\r\n+                }\r\n+                if (!hasMethod) {\r\n+                    logger.warn(new IllegalStateException(\"The methodName \" + inv.getMethodName()\r\n+                            + \" not found in callback service interface ,invoke will be ignored.\"\r\n+                            + \" please update the api interface. url is:\"\r\n+                            + invoker.getUrl()) + \" ,invocation is :\" + inv);\r\n+                    return null;\r\n+                }\r\n+            }\r\n+            RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());\r\n+            Result result = invoker.invoke(inv);\r\n+            return result.thenApply(Function.identity());\r\n+        }\r\n+\r\n+        @Override\r\n+        public void received(Channel channel, Object message) throws RemotingException {\r\n+            if (message instanceof Invocation) {\r\n+                reply((ExchangeChannel) channel, message);\r\n+\r\n+            } else {\r\n+                super.received(channel, message);\r\n+            }\r\n+        }\r\n+\r\n+        @Override\r\n+        public void connected(Channel channel) throws RemotingException {\r\n+            invoke(channel, ON_CONNECT_KEY);\r\n+        }\r\n+\r\n+        @Override\r\n+        public void disconnected(Channel channel) throws RemotingException {\r\n+            if (logger.isDebugEnabled()) {\r\n+                logger.debug(\"disconnected from \" + channel.getRemoteAddress() + \",url:\" + channel.getUrl());\r\n+            }\r\n+            invoke(channel, ON_DISCONNECT_KEY);\r\n+        }\r\n+\r\n+        private void invoke(Channel channel, String methodKey) {\r\n+            Invocation invocation = createInvocation(channel, channel.getUrl(), methodKey);\r\n+            if (invocation != null) {\r\n+                try {\r\n+                    received(channel, invocation);\r\n+                } catch (Throwable t) {\r\n+                    logger.warn(\"Failed to invoke event method \" + invocation.getMethodName() + \"(), cause: \" + t.getMessage(), t);\r\n+                }\r\n+            }\r\n+        }\r\n+\r\n+        /**\r\n+         * FIXME channel.getUrl() always binds to a fixed service, and this service is random.\r\n+         * we can choose to use a common service to carry onConnect event if there's no easy way to get the specific\r\n+         * service this connection is binding to.\r\n+         * @param channel\r\n+         * @param url\r\n+         * @param methodKey\r\n+         * @return\r\n+         */\r\n+        private Invocation createInvocation(Channel channel, URL url, String methodKey) {\r\n+            String method = url.getParameter(methodKey);\r\n+            if (method == null || method.length() == 0) {\r\n+                return null;\r\n+            }\r\n+\r\n+            RpcInvocation invocation = new RpcInvocation(method, url.getParameter(INTERFACE_KEY), \"\", new Class<?>[0], new Object[0]);\r\n+            invocation.setAttachment(PATH_KEY, url.getPath());\r\n+            invocation.setAttachment(GROUP_KEY, url.getParameter(GROUP_KEY));\r\n+            invocation.setAttachment(INTERFACE_KEY, url.getParameter(INTERFACE_KEY));\r\n+            invocation.setAttachment(VERSION_KEY, url.getParameter(VERSION_KEY));\r\n+            if (url.getParameter(STUB_EVENT_KEY, false)) {\r\n+                invocation.setAttachment(STUB_EVENT_KEY, Boolean.TRUE.toString());\r\n+            }\r\n+\r\n+            return invocation;\r\n+        }\r\n+    };\r\n+\r\n+    public DubboProtocol() {\r\n+        INSTANCE = this;\r\n+    }\r\n+\r\n+    public static DubboProtocol getDubboProtocol() {\r\n+        if (INSTANCE == null) {\r\n+            // load\r\n+            ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(DubboProtocol.NAME);\r\n+        }\r\n+\r\n+        return INSTANCE;\r\n+    }\r\n+\r\n+    @Override\r\n+    public Collection<Exporter<?>> getExporters() {\r\n+        return Collections.unmodifiableCollection(exporterMap.values());\r\n+    }\r\n+\r\n+    private boolean isClientSide(Channel channel) {\r\n+        InetSocketAddress address = channel.getRemoteAddress();\r\n+        URL url = channel.getUrl();\r\n+        return url.getPort() == address.getPort() &&\r\n+                NetUtils.filterLocalHost(channel.getUrl().getIp())\r\n+                        .equals(NetUtils.filterLocalHost(address.getAddress().getHostAddress()));\r\n+    }\r\n+\r\n+    Invoker<?> getInvoker(Channel channel, Invocation inv) throws RemotingException {\r\n+        boolean isCallBackServiceInvoke = false;\r\n+        boolean isStubServiceInvoke = false;\r\n+        int port = channel.getLocalAddress().getPort();\r\n+        String path = (String) inv.getObjectAttachments().get(PATH_KEY);\r\n+\r\n+        // if it's callback service on client side\r\n+        isStubServiceInvoke = Boolean.TRUE.toString().equals(inv.getObjectAttachments().get(STUB_EVENT_KEY));\r\n+        if (isStubServiceInvoke) {\r\n+            port = channel.getRemoteAddress().getPort();\r\n+        }\r\n+\r\n+        //callback\r\n+        isCallBackServiceInvoke = isClientSide(channel) && !isStubServiceInvoke;\r\n+        if (isCallBackServiceInvoke) {\r\n+            path += \".\" + inv.getObjectAttachments().get(CALLBACK_SERVICE_KEY);\r\n+            inv.getObjectAttachments().put(IS_CALLBACK_SERVICE_INVOKE, Boolean.TRUE.toString());\r\n+        }\r\n+\r\n+        String serviceKey = serviceKey(\r\n+                port,\r\n+                path,\r\n+                (String) inv.getObjectAttachments().get(VERSION_KEY),\r\n+                (String) inv.getObjectAttachments().get(GROUP_KEY)\r\n+        );\r\n+        DubboExporter<?> exporter = (DubboExporter<?>) exporterMap.get(serviceKey);\r\n+\r\n+        if (exporter == null) {\r\n+            throw new RemotingException(channel, \"Not found exported service: \" + serviceKey + \" in \" + exporterMap.keySet() + \", may be version or group mismatch \" +\r\n+                    \", channel: consumer: \" + channel.getRemoteAddress() + \" --> provider: \" + channel.getLocalAddress() + \", message:\" + getInvocationWithoutData(inv));\r\n+        }\r\n+\r\n+        return exporter.getInvoker();\r\n+    }\r\n+\r\n+    public Collection<Invoker<?>> getInvokers() {\r\n+        return Collections.unmodifiableCollection(invokers);\r\n+    }\r\n+\r\n+    @Override\r\n+    public int getDefaultPort() {\r\n+        return DEFAULT_PORT;\r\n+    }\r\n+\r\n+    @Override\r\n+    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {\r\n+        URL url = invoker.getUrl();\r\n+\r\n+        // export service.\r\n+        String key = serviceKey(url);\r\n+        DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);\r\n+        exporterMap.put(key, exporter);\r\n+\r\n+        //export an stub service for dispatching event\r\n+        Boolean isStubSupportEvent = url.getParameter(STUB_EVENT_KEY, DEFAULT_STUB_EVENT);\r\n+        Boolean isCallbackservice = url.getParameter(IS_CALLBACK_SERVICE, false);\r\n+        if (isStubSupportEvent && !isCallbackservice) {\r\n+            String stubServiceMethods = url.getParameter(STUB_EVENT_METHODS_KEY);\r\n+            if (stubServiceMethods == null || stubServiceMethods.length() == 0) {\r\n+                if (logger.isWarnEnabled()) {\r\n+                    logger.warn(new IllegalStateException(\"consumer [\" + url.getParameter(INTERFACE_KEY) +\r\n+                            \"], has set stubproxy support event ,but no stub methods founded.\"));\r\n+                }\r\n+\r\n+            }\r\n+        }\r\n+\r\n+        openServer(url);\r\n+        optimizeSerialization(url);\r\n+\r\n+        return exporter;\r\n+    }\r\n+\r\n+    private void openServer(URL url) {\r\n+        // find server.\r\n+        String key = url.getAddress();\r\n+        //client can export a service which's only for server to invoke\r\n+        boolean isServer = url.getParameter(IS_SERVER_KEY, true);\r\n+        if (isServer) {\r\n+            ProtocolServer server = serverMap.get(key);\r\n+            if (server == null) {\r\n+                synchronized (this) {\r\n+                    server = serverMap.get(key);\r\n+                    if (server == null) {\r\n+                        serverMap.put(key, createServer(url));\r\n+                    }\r\n+                }\r\n+            } else {\r\n+                // server supports reset, use together with override\r\n+                server.reset(url);\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+    private ProtocolServer createServer(URL url) {\r\n+        url = URLBuilder.from(url)\r\n+                // send readonly event when server closes, it's enabled by default\r\n+                .addParameterIfAbsent(CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString())\r\n+                // enable heartbeat by default\r\n+                .addParameterIfAbsent(HEARTBEAT_KEY, String.valueOf(DEFAULT_HEARTBEAT))\r\n+                .addParameter(CODEC_KEY, DubboCodec.NAME)\r\n+                .build();\r\n+        String str = url.getParameter(SERVER_KEY, DEFAULT_REMOTING_SERVER);\r\n+\r\n+        if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str)) {\r\n+            throw new RpcException(\"Unsupported server type: \" + str + \", url: \" + url);\r\n+        }\r\n+\r\n+        ExchangeServer server;\r\n+        try {\r\n+            server = Exchangers.bind(url, requestHandler);\r\n+        } catch (RemotingException e) {\r\n+            throw new RpcException(\"Fail to start server(url: \" + url + \") \" + e.getMessage(), e);\r\n+        }\r\n+\r\n+        str = url.getParameter(CLIENT_KEY);\r\n+        if (str != null && str.length() > 0) {\r\n+            Set<String> supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions();\r\n+            if (!supportedTypes.contains(str)) {\r\n+                throw new RpcException(\"Unsupported client type: \" + str);\r\n+            }\r\n+        }\r\n+\r\n+        return new DubboProtocolServer(server);\r\n+    }\r\n+\r\n+    private void optimizeSerialization(URL url) throws RpcException {\r\n+        String className = url.getParameter(OPTIMIZER_KEY, \"\");\r\n+        if (StringUtils.isEmpty(className) || optimizers.contains(className)) {\r\n+            return;\r\n+        }\r\n+\r\n+        logger.info(\"Optimizing the serialization process for Kryo, FST, etc...\");\r\n+\r\n+        try {\r\n+            Class clazz = Thread.currentThread().getContextClassLoader().loadClass(className);\r\n+            if (!SerializationOptimizer.class.isAssignableFrom(clazz)) {\r\n+                throw new RpcException(\"The serialization optimizer \" + className + \" isn't an instance of \" + SerializationOptimizer.class.getName());\r\n+            }\r\n+\r\n+            SerializationOptimizer optimizer = (SerializationOptimizer) clazz.newInstance();\r\n+\r\n+            if (optimizer.getSerializableClasses() == null) {\r\n+                return;\r\n+            }\r\n+\r\n+            for (Class c : optimizer.getSerializableClasses()) {\r\n+                SerializableClassRegistry.registerClass(c);\r\n+            }\r\n+\r\n+            optimizers.add(className);\r\n+\r\n+        } catch (ClassNotFoundException e) {\r\n+            throw new RpcException(\"Cannot find the serialization optimizer class: \" + className, e);\r\n+\r\n+        } catch (InstantiationException | IllegalAccessException e) {\r\n+            throw new RpcException(\"Cannot instantiate the serialization optimizer class: \" + className, e);\r\n+\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public <T> Invoker<T> protocolBindingRefer(Class<T> serviceType, URL url) throws RpcException {\r\n+        optimizeSerialization(url);\r\n+\r\n+        // create rpc invoker.\r\n+        DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);\r\n+        invokers.add(invoker);\r\n+\r\n+        return invoker;\r\n+    }\r\n+\r\n+    private ExchangeClient[] getClients(URL url) {\r\n+        // whether to share connection\r\n+\r\n+        boolean useShareConnect = false;\r\n+\r\n+        int connections = url.getParameter(CONNECTIONS_KEY, 0);\r\n+        List<ReferenceCountExchangeClient> shareClients = null;\r\n+        // if not configured, connection is shared, otherwise, one connection for one service\r\n+        if (connections == 0) {\r\n+            useShareConnect = true;\r\n+\r\n+            /*\r\n+             * The xml configuration should have a higher priority than properties.\r\n+             */\r\n+            String shareConnectionsStr = url.getParameter(SHARE_CONNECTIONS_KEY, (String) null);\r\n+            connections = Integer.parseInt(StringUtils.isBlank(shareConnectionsStr) ? ConfigUtils.getProperty(SHARE_CONNECTIONS_KEY,\r\n+                    DEFAULT_SHARE_CONNECTIONS) : shareConnectionsStr);\r\n+            shareClients = getSharedClient(url, connections);\r\n+        }\r\n+\r\n+        ExchangeClient[] clients = new ExchangeClient[connections];\r\n+        for (int i = 0; i < clients.length; i++) {\r\n+            if (useShareConnect) {\r\n+                clients[i] = shareClients.get(i);\r\n+\r\n+            } else {\r\n+                clients[i] = initClient(url);\r\n+            }\r\n+        }\r\n+\r\n+        return clients;\r\n+    }\r\n+\r\n+    /**\r\n+     * Get shared connection\r\n+     *\r\n+     * @param url\r\n+     * @param connectNum connectNum must be greater than or equal to 1\r\n+     */\r\n+    private List<ReferenceCountExchangeClient> getSharedClient(URL url, int connectNum) {\r\n+        String key = url.getAddress();\r\n+        List<ReferenceCountExchangeClient> clients = referenceClientMap.get(key);\r\n+\r\n+        if (checkClientCanUse(clients)) {\r\n+            batchClientRefIncr(clients);\r\n+            return clients;\r\n+        }\r\n+\r\n+        locks.putIfAbsent(key, new Object());\r\n+        synchronized (locks.get(key)) {\r\n+            clients = referenceClientMap.get(key);\r\n+            // double check\r\n+            if (checkClientCanUse(clients)) {\r\n+                batchClientRefIncr(clients);\r\n+                return clients;\r\n+            }\r\n+\r\n+            // connectNum must be greater than or equal to 1\r\n+            connectNum = Math.max(connectNum, 1);\r\n+\r\n+            // If the clients is empty, then the first initialization is\r\n+            if (CollectionUtils.isEmpty(clients)) {\r\n+                clients = buildReferenceCountExchangeClientList(url, connectNum);\r\n+                referenceClientMap.put(key, clients);\r\n+\r\n+            } else {\r\n+                for (int i = 0; i < clients.size(); i++) {\r\n+                    ReferenceCountExchangeClient referenceCountExchangeClient = clients.get(i);\r\n+                    // If there is a client in the list that is no longer available, create a new one to replace him.\r\n+                    if (referenceCountExchangeClient == null || referenceCountExchangeClient.isClosed()) {\r\n+                        clients.set(i, buildReferenceCountExchangeClient(url));\r\n+                        continue;\r\n+                    }\r\n+\r\n+                    referenceCountExchangeClient.incrementAndGetCount();\r\n+                }\r\n+            }\r\n+\r\n+            /*\r\n+             * I understand that the purpose of the remove operation here is to avoid the expired url key\r\n+             * always occupying this memory space.\r\n+             * But \"locks.remove(key);\" can lead to \"synchronized (locks.get(key)) {\" NPE, considering that the key of locks is \"IP + port\",\r\n+             * it will not lead to the expansion of \"locks\" in theory, so I will annotate it here.\r\n+             */\r\n+//            locks.remove(key);\r\n+\r\n+            return clients;\r\n+        }\r\n+    }\r\n+\r\n+    /**\r\n+     * Check if the client list is all available\r\n+     *\r\n+     * @param referenceCountExchangeClients\r\n+     * @return true-available\uff0cfalse-unavailable\r\n+     */\r\n+    private boolean checkClientCanUse(List<ReferenceCountExchangeClient> referenceCountExchangeClients) {\r\n+        if (CollectionUtils.isEmpty(referenceCountExchangeClients)) {\r\n+            return false;\r\n+        }\r\n+\r\n+        for (ReferenceCountExchangeClient referenceCountExchangeClient : referenceCountExchangeClients) {\r\n+            // As long as one client is not available, you need to replace the unavailable client with the available one.\r\n+            if (referenceCountExchangeClient == null || referenceCountExchangeClient.getCount() <= 0 || referenceCountExchangeClient.isClosed()) {\r\n+                return false;\r\n+            }\r\n+        }\r\n+\r\n+        return true;\r\n+    }\r\n+\r\n+    /**\r\n+     * Increase the reference Count if we create new invoker shares same connection, the connection will be closed without any reference.\r\n+     *\r\n+     * @param referenceCountExchangeClients\r\n+     */\r\n+    private void batchClientRefIncr(List<ReferenceCountExchangeClient> referenceCountExchangeClients) {\r\n+        if (CollectionUtils.isEmpty(referenceCountExchangeClients)) {\r\n+            return;\r\n+        }\r\n+\r\n+        for (ReferenceCountExchangeClient referenceCountExchangeClient : referenceCountExchangeClients) {\r\n+            if (referenceCountExchangeClient != null) {\r\n+                referenceCountExchangeClient.incrementAndGetCount();\r\n+            }\r\n+        }\r\n+    }\r\n+\r\n+    /**\r\n+     * Bulk build client\r\n+     *\r\n+     * @param url\r\n+     * @param connectNum\r\n+     * @return\r\n+     */\r\n+    private List<ReferenceCountExchangeClient> buildReferenceCountExchangeClientList(URL url, int connectNum) {\r\n+        List<ReferenceCountExchangeClient> clients = new ArrayList<>();\r\n+\r\n+        for (int i = 0; i < connectNum; i++) {\r\n+            clients.add(buildReferenceCountExchangeClient(url));\r\n+        }\r\n+\r\n+        return clients;\r\n+    }\r\n+\r\n+    /**\r\n+     * Build a single client\r\n+     *\r\n+     * @param url\r\n+     * @return\r\n+     */\r\n+    private ReferenceCountExchangeClient buildReferenceCountExchangeClient(URL url) {\r\n+        ExchangeClient exchangeClient = initClient(url);\r\n+\r\n+        return new ReferenceCountExchangeClient(exchangeClient);\r\n+    }\r\n+\r\n+    /**\r\n+     * Create new connection\r\n+     *\r\n+     * @param url\r\n+     */\r\n+    private ExchangeClient initClient(URL url) {\r\n+\r\n+        // client type setting.\r\n+        String str = url.getParameter(CLIENT_KEY, url.getParameter(SERVER_KEY, DEFAULT_REMOTING_CLIENT));\r\n+\r\n+        url = url.addParameter(CODEC_KEY, DubboCodec.NAME);\r\n+        // enable heartbeat by default\r\n+        url = url.addParameterIfAbsent(HEARTBEAT_KEY, String.valueOf(DEFAULT_HEARTBEAT));\r\n+\r\n+        // BIO is not allowed since it has severe performance issue.\r\n+        if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str)) {\r\n+            throw new RpcException(\"Unsupported client type: \" + str + \",\" +\r\n+                    \" supported client type is \" + StringUtils.join(ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions(), \" \"));\r\n+        }\r\n+\r\n+        ExchangeClient client;\r\n+        try {\r\n+            // connection should be lazy\r\n+            if (url.getParameter(LAZY_CONNECT_KEY, false)) {\r\n+                client = new LazyConnectExchangeClient(url, requestHandler);\r\n+\r\n+            } else {\r\n+                client = Exchangers.connect(url, requestHandler);\r\n+            }\r\n+\r\n+        } catch (RemotingException e) {\r\n+            throw new RpcException(\"Fail to create remoting client for service(\" + url + \"): \" + e.getMessage(), e);\r\n+        }\r\n+\r\n+        return client;\r\n+    }\r\n+\r\n+    @Override\r\n+    public void destroy() {\r\n+        for (String key : new ArrayList<>(serverMap.keySet())) {\r\n+            ProtocolServer protocolServer = serverMap.remove(key);\r\n+\r\n+            if (protocolServer == null) {\r\n+                continue;\r\n+            }\r\n+\r\n+            RemotingServer server = protocolServer.getRemotingServer();\r\n+\r\n+            try {\r\n+                if (logger.isInfoEnabled()) {\r\n+                    logger.info(\"Close dubbo server: \" + server.getLocalAddress());\r\n+                }\r\n+\r\n+                server.close(ConfigurationUtils.getServerShutdownTimeout());\r\n+\r\n+            } catch (Throwable t) {\r\n+                logger.warn(t.getMessage(), t);\r\n+            }\r\n+        }\r\n+\r\n+        for (String key : new ArrayList<>(referenceClientMap.keySet())) {\r\n+            List<ReferenceCountExchangeClient> clients = referenceClientMap.remove(key);\r\n+\r\n+            if (CollectionUtils.isEmpty(clients)) {\r\n+                continue;\r\n+            }\r\n+\r\n+            for (ReferenceCountExchangeClient client : clients) {\r\n+                closeReferenceCountExchangeClient(client);\r\n+            }\r\n+        }\r\n+\r\n+        super.destroy();\r\n+    }\r\n+\r\n+    /**\r\n+     * close ReferenceCountExchangeClient\r\n+     *\r\n+     * @param client\r\n+     */\r\n+    private void closeReferenceCountExchangeClient(ReferenceCountExchangeClient client) {\r\n+        if (client == null) {\r\n+            return;\r\n+        }\r\n+\r\n+        try {\r\n+            if (logger.isInfoEnabled()) {\r\n+                logger.info(\"Close dubbo connect: \" + client.getLocalAddress() + \"-->\" + client.getRemoteAddress());\r\n+            }\r\n+\r\n+            client.close(ConfigurationUtils.getServerShutdownTimeout());\r\n+\r\n+            // TODO\r\n+            /*\r\n+             * At this time, ReferenceCountExchangeClient#client has been replaced with LazyConnectExchangeClient.\r\n+             * Do you need to call client.close again to ensure that LazyConnectExchangeClient is also closed?\r\n+             */\r\n+\r\n+        } catch (Throwable t) {\r\n+            logger.warn(t.getMessage(), t);\r\n+        }\r\n+    }\r\n+\r\n+    /**\r\n+     * only log body in debugger mode for size & security consideration.\r\n+     *\r\n+     * @param invocation\r\n+     * @return\r\n+     */\r\n+    private Invocation getInvocationWithoutData(Invocation invocation) {\r\n+        if (logger.isDebugEnabled()) {\r\n+            return invocation;\r\n+        }\r\n+        if (invocation instanceof RpcInvocation) {\r\n+            RpcInvocation rpcInvocation = (RpcInvocation) invocation;\r\n+            rpcInvocation.setArguments(null);\r\n+            return rpcInvocation;\r\n+        }\r\n+        return invocation;\r\n+    }\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolServer.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolServer.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,62 +1,62 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.common.utils.StringUtils;\n-import org.apache.dubbo.remoting.RemotingServer;\n-import org.apache.dubbo.rpc.ProtocolServer;\n-\n-public class DubboProtocolServer implements ProtocolServer {\n-\n-    private RemotingServer server;\n-    private String address;\n-\n-    public DubboProtocolServer(RemotingServer server) {\n-        this.server = server;\n-    }\n-\n-    @Override\n-    public RemotingServer getRemotingServer() {\n-        return server;\n-    }\n-\n-    @Override\n-    public String getAddress() {\n-        return StringUtils.isNotEmpty(address) ? address : server.getUrl().getAddress();\n-    }\n-\n-    @Override\n-    public void setAddress(String address) {\n-        this.address = address;\n-    }\n-\n-    @Override\n-    public URL getUrl() {\n-        return server.getUrl();\n-    }\n-\n-    @Override\n-    public void reset(URL url) {\n-        server.reset(url);\n-    }\n-\n-    @Override\n-    public void close() {\n-        server.close();\n-    }\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.common.utils.StringUtils;\r\n+import org.apache.dubbo.remoting.RemotingServer;\r\n+import org.apache.dubbo.rpc.ProtocolServer;\r\n+\r\n+public class DubboProtocolServer implements ProtocolServer {\r\n+\r\n+    private RemotingServer server;\r\n+    private String address;\r\n+\r\n+    public DubboProtocolServer(RemotingServer server) {\r\n+        this.server = server;\r\n+    }\r\n+\r\n+    @Override\r\n+    public RemotingServer getRemotingServer() {\r\n+        return server;\r\n+    }\r\n+\r\n+    @Override\r\n+    public String getAddress() {\r\n+        return StringUtils.isNotEmpty(address) ? address : server.getUrl().getAddress();\r\n+    }\r\n+\r\n+    @Override\r\n+    public void setAddress(String address) {\r\n+        this.address = address;\r\n+    }\r\n+\r\n+    @Override\r\n+    public URL getUrl() {\r\n+        return server.getUrl();\r\n+    }\r\n+\r\n+    @Override\r\n+    public void reset(URL url) {\r\n+        server.reset(url);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void close() {\r\n+        server.close();\r\n+    }\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/LazyConnectExchangeClient.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,269 +1,269 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-import org.apache.dubbo.common.Parameters;\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.common.logger.Logger;\n-import org.apache.dubbo.common.logger.LoggerFactory;\n-import org.apache.dubbo.common.utils.NetUtils;\n-import org.apache.dubbo.remoting.ChannelHandler;\n-import org.apache.dubbo.remoting.RemotingException;\n-import org.apache.dubbo.remoting.exchange.ExchangeClient;\n-import org.apache.dubbo.remoting.exchange.ExchangeHandler;\n-import org.apache.dubbo.remoting.exchange.Exchangers;\n-\n-import java.net.InetSocketAddress;\n-import java.util.concurrent.CompletableFuture;\n-import java.util.concurrent.ExecutorService;\n-import java.util.concurrent.atomic.AtomicLong;\n-import java.util.concurrent.locks.Lock;\n-import java.util.concurrent.locks.ReentrantLock;\n-\n-import static org.apache.dubbo.remoting.Constants.SEND_RECONNECT_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.DEFAULT_LAZY_CONNECT_INITIAL_STATE;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.LAZY_CONNECT_INITIAL_STATE_KEY;\n-\n-/**\n- * dubbo protocol support class.\n- */\n-@SuppressWarnings(\"deprecation\")\n-final class LazyConnectExchangeClient implements ExchangeClient {\n-\n-    /**\n-     * when this warning rises from invocation, program probably have bug.\n-     */\n-    protected static final String REQUEST_WITH_WARNING_KEY = \"lazyclient_request_with_warning\";\n-    private final static Logger logger = LoggerFactory.getLogger(LazyConnectExchangeClient.class);\n-    protected final boolean requestWithWarning;\n-    private final URL url;\n-    private final ExchangeHandler requestHandler;\n-    private final Lock connectLock = new ReentrantLock();\n-    private final int warning_period = 5000;\n-    /**\n-     * lazy connect, initial state for connection\n-     */\n-    private final boolean initialState;\n-    private volatile ExchangeClient client;\n-    private AtomicLong warningcount = new AtomicLong(0);\n-\n-    public LazyConnectExchangeClient(URL url, ExchangeHandler requestHandler) {\n-        // lazy connect, need set send.reconnect = true, to avoid channel bad status.\n-        this.url = url.addParameter(SEND_RECONNECT_KEY, Boolean.TRUE.toString());\n-        this.requestHandler = requestHandler;\n-        this.initialState = url.getParameter(LAZY_CONNECT_INITIAL_STATE_KEY, DEFAULT_LAZY_CONNECT_INITIAL_STATE);\n-        this.requestWithWarning = url.getParameter(REQUEST_WITH_WARNING_KEY, false);\n-    }\n-\n-    private void initClient() throws RemotingException {\n-        if (client != null) {\n-            return;\n-        }\n-        if (logger.isInfoEnabled()) {\n-            logger.info(\"Lazy connect to \" + url);\n-        }\n-        connectLock.lock();\n-        try {\n-            if (client != null) {\n-                return;\n-            }\n-            this.client = Exchangers.connect(url, requestHandler);\n-        } finally {\n-            connectLock.unlock();\n-        }\n-    }\n-\n-    @Override\n-    public CompletableFuture<Object> request(Object request) throws RemotingException {\n-        warning();\n-        initClient();\n-        return client.request(request);\n-    }\n-\n-    @Override\n-    public URL getUrl() {\n-        return url;\n-    }\n-\n-    @Override\n-    public InetSocketAddress getRemoteAddress() {\n-        if (client == null) {\n-            return InetSocketAddress.createUnresolved(url.getHost(), url.getPort());\n-        } else {\n-            return client.getRemoteAddress();\n-        }\n-    }\n-\n-    @Override\n-    public CompletableFuture<Object> request(Object request, int timeout) throws RemotingException {\n-        warning();\n-        initClient();\n-        return client.request(request, timeout);\n-    }\n-\n-    @Override\n-    public CompletableFuture<Object> request(Object request, ExecutorService executor) throws RemotingException {\n-        warning();\n-        initClient();\n-        return client.request(request, executor);\n-    }\n-\n-    @Override\n-    public CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException {\n-        warning();\n-        initClient();\n-        return client.request(request, timeout, executor);\n-    }\n-\n-    /**\n-     * If {@link #REQUEST_WITH_WARNING_KEY} is configured, then warn once every 5000 invocations.\n-     */\n-    private void warning() {\n-        if (requestWithWarning) {\n-            if (warningcount.get() % warning_period == 0) {\n-                logger.warn(url.getAddress() + \" \" + url.getServiceKey() + \" safe guard client , should not be called ,must have a bug.\");\n-            }\n-            warningcount.incrementAndGet();\n-        }\n-    }\n-\n-    @Override\n-    public ChannelHandler getChannelHandler() {\n-        checkClient();\n-        return client.getChannelHandler();\n-    }\n-\n-    @Override\n-    public boolean isConnected() {\n-        if (client == null) {\n-            return initialState;\n-        } else {\n-            return client.isConnected();\n-        }\n-    }\n-\n-    @Override\n-    public InetSocketAddress getLocalAddress() {\n-        if (client == null) {\n-            return InetSocketAddress.createUnresolved(NetUtils.getLocalHost(), 0);\n-        } else {\n-            return client.getLocalAddress();\n-        }\n-    }\n-\n-    @Override\n-    public ExchangeHandler getExchangeHandler() {\n-        return requestHandler;\n-    }\n-\n-    @Override\n-    public void send(Object message) throws RemotingException {\n-        initClient();\n-        client.send(message);\n-    }\n-\n-    @Override\n-    public void send(Object message, boolean sent) throws RemotingException {\n-        initClient();\n-        client.send(message, sent);\n-    }\n-\n-    @Override\n-    public boolean isClosed() {\n-        if (client != null) {\n-            return client.isClosed();\n-        } else {\n-            return false;\n-        }\n-    }\n-\n-    @Override\n-    public void close() {\n-        if (client != null) {\n-            client.close();\n-        }\n-    }\n-\n-    @Override\n-    public void close(int timeout) {\n-        if (client != null) {\n-            client.close(timeout);\n-        }\n-    }\n-\n-    @Override\n-    public void startClose() {\n-        if (client != null) {\n-            client.startClose();\n-        }\n-    }\n-\n-    @Override\n-    public void reset(URL url) {\n-        checkClient();\n-        client.reset(url);\n-    }\n-\n-    @Override\n-    @Deprecated\n-    public void reset(Parameters parameters) {\n-        reset(getUrl().addParameters(parameters.getParameters()));\n-    }\n-\n-    @Override\n-    public void reconnect() throws RemotingException {\n-        checkClient();\n-        client.reconnect();\n-    }\n-\n-    @Override\n-    public Object getAttribute(String key) {\n-        if (client == null) {\n-            return null;\n-        } else {\n-            return client.getAttribute(key);\n-        }\n-    }\n-\n-    @Override\n-    public void setAttribute(String key, Object value) {\n-        checkClient();\n-        client.setAttribute(key, value);\n-    }\n-\n-    @Override\n-    public void removeAttribute(String key) {\n-        checkClient();\n-        client.removeAttribute(key);\n-    }\n-\n-    @Override\n-    public boolean hasAttribute(String key) {\n-        if (client == null) {\n-            return false;\n-        } else {\n-            return client.hasAttribute(key);\n-        }\n-    }\n-\n-    private void checkClient() {\n-        if (client == null) {\n-            throw new IllegalStateException(\n-                    \"LazyConnectExchangeClient state error. the client has not be init .url:\" + url);\n-        }\n-    }\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+import org.apache.dubbo.common.Parameters;\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.common.logger.Logger;\r\n+import org.apache.dubbo.common.logger.LoggerFactory;\r\n+import org.apache.dubbo.common.utils.NetUtils;\r\n+import org.apache.dubbo.remoting.ChannelHandler;\r\n+import org.apache.dubbo.remoting.RemotingException;\r\n+import org.apache.dubbo.remoting.exchange.ExchangeClient;\r\n+import org.apache.dubbo.remoting.exchange.ExchangeHandler;\r\n+import org.apache.dubbo.remoting.exchange.Exchangers;\r\n+\r\n+import java.net.InetSocketAddress;\r\n+import java.util.concurrent.CompletableFuture;\r\n+import java.util.concurrent.ExecutorService;\r\n+import java.util.concurrent.atomic.AtomicLong;\r\n+import java.util.concurrent.locks.Lock;\r\n+import java.util.concurrent.locks.ReentrantLock;\r\n+\r\n+import static org.apache.dubbo.remoting.Constants.SEND_RECONNECT_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.DEFAULT_LAZY_CONNECT_INITIAL_STATE;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.LAZY_CONNECT_INITIAL_STATE_KEY;\r\n+\r\n+/**\r\n+ * dubbo protocol support class.\r\n+ */\r\n+@SuppressWarnings(\"deprecation\")\r\n+final class LazyConnectExchangeClient implements ExchangeClient {\r\n+\r\n+    /**\r\n+     * when this warning rises from invocation, program probably have bug.\r\n+     */\r\n+    protected static final String REQUEST_WITH_WARNING_KEY = \"lazyclient_request_with_warning\";\r\n+    private final static Logger logger = LoggerFactory.getLogger(LazyConnectExchangeClient.class);\r\n+    protected final boolean requestWithWarning;\r\n+    private final URL url;\r\n+    private final ExchangeHandler requestHandler;\r\n+    private final Lock connectLock = new ReentrantLock();\r\n+    private final int warning_period = 5000;\r\n+    /**\r\n+     * lazy connect, initial state for connection\r\n+     */\r\n+    private final boolean initialState;\r\n+    private volatile ExchangeClient client;\r\n+    private AtomicLong warningcount = new AtomicLong(0);\r\n+\r\n+    public LazyConnectExchangeClient(URL url, ExchangeHandler requestHandler) {\r\n+        // lazy connect, need set send.reconnect = true, to avoid channel bad status.\r\n+        this.url = url.addParameter(SEND_RECONNECT_KEY, Boolean.TRUE.toString());\r\n+        this.requestHandler = requestHandler;\r\n+        this.initialState = url.getParameter(LAZY_CONNECT_INITIAL_STATE_KEY, DEFAULT_LAZY_CONNECT_INITIAL_STATE);\r\n+        this.requestWithWarning = url.getParameter(REQUEST_WITH_WARNING_KEY, false);\r\n+    }\r\n+\r\n+    private void initClient() throws RemotingException {\r\n+        if (client != null) {\r\n+            return;\r\n+        }\r\n+        if (logger.isInfoEnabled()) {\r\n+            logger.info(\"Lazy connect to \" + url);\r\n+        }\r\n+        connectLock.lock();\r\n+        try {\r\n+            if (client != null) {\r\n+                return;\r\n+            }\r\n+            this.client = Exchangers.connect(url, requestHandler);\r\n+        } finally {\r\n+            connectLock.unlock();\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public CompletableFuture<Object> request(Object request) throws RemotingException {\r\n+        warning();\r\n+        initClient();\r\n+        return client.request(request);\r\n+    }\r\n+\r\n+    @Override\r\n+    public URL getUrl() {\r\n+        return url;\r\n+    }\r\n+\r\n+    @Override\r\n+    public InetSocketAddress getRemoteAddress() {\r\n+        if (client == null) {\r\n+            return InetSocketAddress.createUnresolved(url.getHost(), url.getPort());\r\n+        } else {\r\n+            return client.getRemoteAddress();\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public CompletableFuture<Object> request(Object request, int timeout) throws RemotingException {\r\n+        warning();\r\n+        initClient();\r\n+        return client.request(request, timeout);\r\n+    }\r\n+\r\n+    @Override\r\n+    public CompletableFuture<Object> request(Object request, ExecutorService executor) throws RemotingException {\r\n+        warning();\r\n+        initClient();\r\n+        return client.request(request, executor);\r\n+    }\r\n+\r\n+    @Override\r\n+    public CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException {\r\n+        warning();\r\n+        initClient();\r\n+        return client.request(request, timeout, executor);\r\n+    }\r\n+\r\n+    /**\r\n+     * If {@link #REQUEST_WITH_WARNING_KEY} is configured, then warn once every 5000 invocations.\r\n+     */\r\n+    private void warning() {\r\n+        if (requestWithWarning) {\r\n+            if (warningcount.get() % warning_period == 0) {\r\n+                logger.warn(url.getAddress() + \" \" + url.getServiceKey() + \" safe guard client , should not be called ,must have a bug.\");\r\n+            }\r\n+            warningcount.incrementAndGet();\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public ChannelHandler getChannelHandler() {\r\n+        checkClient();\r\n+        return client.getChannelHandler();\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean isConnected() {\r\n+        if (client == null) {\r\n+            return initialState;\r\n+        } else {\r\n+            return client.isConnected();\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public InetSocketAddress getLocalAddress() {\r\n+        if (client == null) {\r\n+            return InetSocketAddress.createUnresolved(NetUtils.getLocalHost(), 0);\r\n+        } else {\r\n+            return client.getLocalAddress();\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public ExchangeHandler getExchangeHandler() {\r\n+        return requestHandler;\r\n+    }\r\n+\r\n+    @Override\r\n+    public void send(Object message) throws RemotingException {\r\n+        initClient();\r\n+        client.send(message);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void send(Object message, boolean sent) throws RemotingException {\r\n+        initClient();\r\n+        client.send(message, sent);\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean isClosed() {\r\n+        if (client != null) {\r\n+            return client.isClosed();\r\n+        } else {\r\n+            return false;\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public void close() {\r\n+        if (client != null) {\r\n+            client.close();\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public void close(int timeout) {\r\n+        if (client != null) {\r\n+            client.close(timeout);\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public void startClose() {\r\n+        if (client != null) {\r\n+            client.startClose();\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public void reset(URL url) {\r\n+        checkClient();\r\n+        client.reset(url);\r\n+    }\r\n+\r\n+    @Override\r\n+    @Deprecated\r\n+    public void reset(Parameters parameters) {\r\n+        reset(getUrl().addParameters(parameters.getParameters()));\r\n+    }\r\n+\r\n+    @Override\r\n+    public void reconnect() throws RemotingException {\r\n+        checkClient();\r\n+        client.reconnect();\r\n+    }\r\n+\r\n+    @Override\r\n+    public Object getAttribute(String key) {\r\n+        if (client == null) {\r\n+            return null;\r\n+        } else {\r\n+            return client.getAttribute(key);\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public void setAttribute(String key, Object value) {\r\n+        checkClient();\r\n+        client.setAttribute(key, value);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void removeAttribute(String key) {\r\n+        checkClient();\r\n+        client.removeAttribute(key);\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean hasAttribute(String key) {\r\n+        if (client == null) {\r\n+            return false;\r\n+        } else {\r\n+            return client.hasAttribute(key);\r\n+        }\r\n+    }\r\n+\r\n+    private void checkClient() {\r\n+        if (client == null) {\r\n+            throw new IllegalStateException(\r\n+                    \"LazyConnectExchangeClient state error. the client has not be init .url:\" + url);\r\n+        }\r\n+    }\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/ReferenceCountExchangeClient.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,211 +1,211 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo;\n-\n-\n-import org.apache.dubbo.common.Parameters;\n-import org.apache.dubbo.common.URL;\n-import org.apache.dubbo.remoting.ChannelHandler;\n-import org.apache.dubbo.remoting.RemotingException;\n-import org.apache.dubbo.remoting.exchange.ExchangeClient;\n-import org.apache.dubbo.remoting.exchange.ExchangeHandler;\n-\n-import java.net.InetSocketAddress;\n-import java.util.concurrent.CompletableFuture;\n-import java.util.concurrent.ExecutorService;\n-import java.util.concurrent.atomic.AtomicInteger;\n-\n-import static org.apache.dubbo.remoting.Constants.SEND_RECONNECT_KEY;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.LAZY_CONNECT_INITIAL_STATE_KEY;\n-\n-/**\n- * dubbo protocol support class.\n- */\n-@SuppressWarnings(\"deprecation\")\n-final class ReferenceCountExchangeClient implements ExchangeClient {\n-\n-    private final URL url;\n-    private final AtomicInteger referenceCount = new AtomicInteger(0);\n-\n-    private ExchangeClient client;\n-\n-    public ReferenceCountExchangeClient(ExchangeClient client) {\n-        this.client = client;\n-        referenceCount.incrementAndGet();\n-        this.url = client.getUrl();\n-    }\n-\n-    @Override\n-    public void reset(URL url) {\n-        client.reset(url);\n-    }\n-\n-    @Override\n-    public CompletableFuture<Object> request(Object request) throws RemotingException {\n-        return client.request(request);\n-    }\n-\n-    @Override\n-    public URL getUrl() {\n-        return client.getUrl();\n-    }\n-\n-    @Override\n-    public InetSocketAddress getRemoteAddress() {\n-        return client.getRemoteAddress();\n-    }\n-\n-    @Override\n-    public ChannelHandler getChannelHandler() {\n-        return client.getChannelHandler();\n-    }\n-\n-    @Override\n-    public CompletableFuture<Object> request(Object request, int timeout) throws RemotingException {\n-        return client.request(request, timeout);\n-    }\n-\n-    @Override\n-    public CompletableFuture<Object> request(Object request, ExecutorService executor) throws RemotingException {\n-        return client.request(request, executor);\n-    }\n-\n-    @Override\n-    public CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException {\n-        return client.request(request, timeout, executor);\n-    }\n-\n-    @Override\n-    public boolean isConnected() {\n-        return client.isConnected();\n-    }\n-\n-    @Override\n-    public void reconnect() throws RemotingException {\n-        client.reconnect();\n-    }\n-\n-    @Override\n-    public InetSocketAddress getLocalAddress() {\n-        return client.getLocalAddress();\n-    }\n-\n-    @Override\n-    public boolean hasAttribute(String key) {\n-        return client.hasAttribute(key);\n-    }\n-\n-    @Override\n-    public void reset(Parameters parameters) {\n-        client.reset(parameters);\n-    }\n-\n-    @Override\n-    public void send(Object message) throws RemotingException {\n-        client.send(message);\n-    }\n-\n-    @Override\n-    public ExchangeHandler getExchangeHandler() {\n-        return client.getExchangeHandler();\n-    }\n-\n-    @Override\n-    public Object getAttribute(String key) {\n-        return client.getAttribute(key);\n-    }\n-\n-    @Override\n-    public void send(Object message, boolean sent) throws RemotingException {\n-        client.send(message, sent);\n-    }\n-\n-    @Override\n-    public void setAttribute(String key, Object value) {\n-        client.setAttribute(key, value);\n-    }\n-\n-    @Override\n-    public void removeAttribute(String key) {\n-        client.removeAttribute(key);\n-    }\n-\n-    /**\n-     * close() is not idempotent any longer\n-     */\n-    @Override\n-    public void close() {\n-        close(0);\n-    }\n-\n-    @Override\n-    public void close(int timeout) {\n-        if (referenceCount.decrementAndGet() <= 0) {\n-            if (timeout == 0) {\n-                client.close();\n-\n-            } else {\n-                client.close(timeout);\n-            }\n-\n-            replaceWithLazyClient();\n-        }\n-    }\n-\n-    @Override\n-    public void startClose() {\n-        client.startClose();\n-    }\n-\n-    /**\n-     * when closing the client, the client needs to be set to LazyConnectExchangeClient, and if a new call is made,\n-     * the client will \"resurrect\".\n-     *\n-     * @return\n-     */\n-    private void replaceWithLazyClient() {\n-        // this is a defensive operation to avoid client is closed by accident, the initial state of the client is false\n-        URL lazyUrl = url.addParameter(LAZY_CONNECT_INITIAL_STATE_KEY, Boolean.TRUE)\n-                //.addParameter(RECONNECT_KEY, Boolean.FALSE)\n-                .addParameter(SEND_RECONNECT_KEY, Boolean.TRUE.toString())\n-                .addParameter(LazyConnectExchangeClient.REQUEST_WITH_WARNING_KEY, true);\n-\n-        /**\n-         * the order of judgment in the if statement cannot be changed.\n-         */\n-        if (!(client instanceof LazyConnectExchangeClient) || client.isClosed()) {\n-            client = new LazyConnectExchangeClient(lazyUrl, client.getExchangeHandler());\n-        }\n-    }\n-\n-    @Override\n-    public boolean isClosed() {\n-        return client.isClosed();\n-    }\n-\n-    /**\n-     * The reference count of current ExchangeClient, connection will be closed if all invokers destroyed.\n-     */\n-    public void incrementAndGetCount() {\n-        referenceCount.incrementAndGet();\n-    }\n-\n-    public int getCount() {\n-        return referenceCount.get();\n-    }\n-}\n-\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo;\r\n+\r\n+\r\n+import org.apache.dubbo.common.Parameters;\r\n+import org.apache.dubbo.common.URL;\r\n+import org.apache.dubbo.remoting.ChannelHandler;\r\n+import org.apache.dubbo.remoting.RemotingException;\r\n+import org.apache.dubbo.remoting.exchange.ExchangeClient;\r\n+import org.apache.dubbo.remoting.exchange.ExchangeHandler;\r\n+\r\n+import java.net.InetSocketAddress;\r\n+import java.util.concurrent.CompletableFuture;\r\n+import java.util.concurrent.ExecutorService;\r\n+import java.util.concurrent.atomic.AtomicInteger;\r\n+\r\n+import static org.apache.dubbo.remoting.Constants.SEND_RECONNECT_KEY;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.LAZY_CONNECT_INITIAL_STATE_KEY;\r\n+\r\n+/**\r\n+ * dubbo protocol support class.\r\n+ */\r\n+@SuppressWarnings(\"deprecation\")\r\n+final class ReferenceCountExchangeClient implements ExchangeClient {\r\n+\r\n+    private final URL url;\r\n+    private final AtomicInteger referenceCount = new AtomicInteger(0);\r\n+\r\n+    private ExchangeClient client;\r\n+\r\n+    public ReferenceCountExchangeClient(ExchangeClient client) {\r\n+        this.client = client;\r\n+        referenceCount.incrementAndGet();\r\n+        this.url = client.getUrl();\r\n+    }\r\n+\r\n+    @Override\r\n+    public void reset(URL url) {\r\n+        client.reset(url);\r\n+    }\r\n+\r\n+    @Override\r\n+    public CompletableFuture<Object> request(Object request) throws RemotingException {\r\n+        return client.request(request);\r\n+    }\r\n+\r\n+    @Override\r\n+    public URL getUrl() {\r\n+        return client.getUrl();\r\n+    }\r\n+\r\n+    @Override\r\n+    public InetSocketAddress getRemoteAddress() {\r\n+        return client.getRemoteAddress();\r\n+    }\r\n+\r\n+    @Override\r\n+    public ChannelHandler getChannelHandler() {\r\n+        return client.getChannelHandler();\r\n+    }\r\n+\r\n+    @Override\r\n+    public CompletableFuture<Object> request(Object request, int timeout) throws RemotingException {\r\n+        return client.request(request, timeout);\r\n+    }\r\n+\r\n+    @Override\r\n+    public CompletableFuture<Object> request(Object request, ExecutorService executor) throws RemotingException {\r\n+        return client.request(request, executor);\r\n+    }\r\n+\r\n+    @Override\r\n+    public CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException {\r\n+        return client.request(request, timeout, executor);\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean isConnected() {\r\n+        return client.isConnected();\r\n+    }\r\n+\r\n+    @Override\r\n+    public void reconnect() throws RemotingException {\r\n+        client.reconnect();\r\n+    }\r\n+\r\n+    @Override\r\n+    public InetSocketAddress getLocalAddress() {\r\n+        return client.getLocalAddress();\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean hasAttribute(String key) {\r\n+        return client.hasAttribute(key);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void reset(Parameters parameters) {\r\n+        client.reset(parameters);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void send(Object message) throws RemotingException {\r\n+        client.send(message);\r\n+    }\r\n+\r\n+    @Override\r\n+    public ExchangeHandler getExchangeHandler() {\r\n+        return client.getExchangeHandler();\r\n+    }\r\n+\r\n+    @Override\r\n+    public Object getAttribute(String key) {\r\n+        return client.getAttribute(key);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void send(Object message, boolean sent) throws RemotingException {\r\n+        client.send(message, sent);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void setAttribute(String key, Object value) {\r\n+        client.setAttribute(key, value);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void removeAttribute(String key) {\r\n+        client.removeAttribute(key);\r\n+    }\r\n+\r\n+    /**\r\n+     * close() is not idempotent any longer\r\n+     */\r\n+    @Override\r\n+    public void close() {\r\n+        close(0);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void close(int timeout) {\r\n+        if (referenceCount.decrementAndGet() <= 0) {\r\n+            if (timeout == 0) {\r\n+                client.close();\r\n+\r\n+            } else {\r\n+                client.close(timeout);\r\n+            }\r\n+\r\n+            replaceWithLazyClient();\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public void startClose() {\r\n+        client.startClose();\r\n+    }\r\n+\r\n+    /**\r\n+     * when closing the client, the client needs to be set to LazyConnectExchangeClient, and if a new call is made,\r\n+     * the client will \"resurrect\".\r\n+     *\r\n+     * @return\r\n+     */\r\n+    private void replaceWithLazyClient() {\r\n+        // this is a defensive operation to avoid client is closed by accident, the initial state of the client is false\r\n+        URL lazyUrl = url.addParameter(LAZY_CONNECT_INITIAL_STATE_KEY, Boolean.TRUE)\r\n+                //.addParameter(RECONNECT_KEY, Boolean.FALSE)\r\n+                .addParameter(SEND_RECONNECT_KEY, Boolean.TRUE.toString())\r\n+                .addParameter(LazyConnectExchangeClient.REQUEST_WITH_WARNING_KEY, true);\r\n+\r\n+        /**\r\n+         * the order of judgment in the if statement cannot be changed.\r\n+         */\r\n+        if (!(client instanceof LazyConnectExchangeClient) || client.isClosed()) {\r\n+            client = new LazyConnectExchangeClient(lazyUrl, client.getExchangeHandler());\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public boolean isClosed() {\r\n+        return client.isClosed();\r\n+    }\r\n+\r\n+    /**\r\n+     * The reference count of current ExchangeClient, connection will be closed if all invokers destroyed.\r\n+     */\r\n+    public void incrementAndGetCount() {\r\n+        referenceCount.incrementAndGet();\r\n+    }\r\n+\r\n+    public int getCount() {\r\n+        return referenceCount.get();\r\n+    }\r\n+}\r\n+\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,203 +1,203 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo.filter;\n-\n-import org.apache.dubbo.common.constants.CommonConstants;\n-import org.apache.dubbo.common.extension.Activate;\n-import org.apache.dubbo.common.logger.Logger;\n-import org.apache.dubbo.common.logger.LoggerFactory;\n-import org.apache.dubbo.common.utils.ReflectUtils;\n-import org.apache.dubbo.rpc.Filter;\n-import org.apache.dubbo.rpc.Invocation;\n-import org.apache.dubbo.rpc.Invoker;\n-import org.apache.dubbo.rpc.Result;\n-import org.apache.dubbo.rpc.RpcException;\n-import org.apache.dubbo.rpc.model.ApplicationModel;\n-import org.apache.dubbo.rpc.model.AsyncMethodInfo;\n-import org.apache.dubbo.rpc.model.ConsumerModel;\n-\n-import java.lang.reflect.InvocationTargetException;\n-import java.lang.reflect.Method;\n-\n-import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;\n-import static org.apache.dubbo.rpc.protocol.dubbo.Constants.ASYNC_METHOD_INFO;\n-\n-/**\n- * EventFilter\n- */\n-@Activate(group = CommonConstants.CONSUMER)\n-public class FutureFilter implements Filter, Filter.Listener {\n-\n-    protected static final Logger logger = LoggerFactory.getLogger(FutureFilter.class);\n-\n-    @Override\n-    public Result invoke(final Invoker<?> invoker, final Invocation invocation) throws RpcException {\n-        fireInvokeCallback(invoker, invocation);\n-        // need to configure if there's return value before the invocation in order to help invoker to judge if it's\n-        // necessary to return future.\n-        return invoker.invoke(invocation);\n-    }\n-\n-    @Override\n-    public void onResponse(Result result, Invoker<?> invoker, Invocation invocation) {\n-        if (result.hasException()) {\n-            fireThrowCallback(invoker, invocation, result.getException());\n-        } else {\n-            fireReturnCallback(invoker, invocation, result.getValue());\n-        }\n-    }\n-\n-    @Override\n-    public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {\n-        fireThrowCallback(invoker, invocation, t);\n-    }\n-\n-    private void fireInvokeCallback(final Invoker<?> invoker, final Invocation invocation) {\n-        final AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);\n-        if (asyncMethodInfo == null) {\n-            return;\n-        }\n-        final Method onInvokeMethod = asyncMethodInfo.getOninvokeMethod();\n-        final Object onInvokeInst = asyncMethodInfo.getOninvokeInstance();\n-\n-        if (onInvokeMethod == null && onInvokeInst == null) {\n-            return;\n-        }\n-        if (onInvokeMethod == null || onInvokeInst == null) {\n-            throw new IllegalStateException(\"service:\" + invoker.getUrl().getServiceKey() + \" has a oninvoke callback config , but no such \" + (onInvokeMethod == null ? \"method\" : \"instance\") + \" found. url:\" + invoker.getUrl());\n-        }\n-\n-        ReflectUtils.makeAccessible(onInvokeMethod);\n-        Object[] params = invocation.getArguments();\n-        try {\n-            onInvokeMethod.invoke(onInvokeInst, params);\n-        } catch (InvocationTargetException e) {\n-            fireThrowCallback(invoker, invocation, e.getTargetException());\n-        } catch (Throwable e) {\n-            fireThrowCallback(invoker, invocation, e);\n-        }\n-    }\n-\n-    private void fireReturnCallback(final Invoker<?> invoker, final Invocation invocation, final Object result) {\n-        final AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);\n-        if (asyncMethodInfo == null) {\n-            return;\n-        }\n-\n-        final Method onReturnMethod = asyncMethodInfo.getOnreturnMethod();\n-        final Object onReturnInst = asyncMethodInfo.getOnreturnInstance();\n-\n-        //not set onreturn callback\n-        if (onReturnMethod == null && onReturnInst == null) {\n-            return;\n-        }\n-\n-        if (onReturnMethod == null || onReturnInst == null) {\n-            throw new IllegalStateException(\"service:\" + invoker.getUrl().getServiceKey() + \" has a onreturn callback config , but no such \" + (onReturnMethod == null ? \"method\" : \"instance\") + \" found. url:\" + invoker.getUrl());\n-        }\n-        ReflectUtils.makeAccessible(onReturnMethod);\n-\n-        Object[] args = invocation.getArguments();\n-        Object[] params;\n-        Class<?>[] rParaTypes = onReturnMethod.getParameterTypes();\n-        if (rParaTypes.length > 1) {\n-            if (rParaTypes.length == 2 && rParaTypes[1].isAssignableFrom(Object[].class)) {\n-                params = new Object[2];\n-                params[0] = result;\n-                params[1] = args;\n-            } else {\n-                params = new Object[args.length + 1];\n-                params[0] = result;\n-                System.arraycopy(args, 0, params, 1, args.length);\n-            }\n-        } else {\n-            params = new Object[]{result};\n-        }\n-        try {\n-            onReturnMethod.invoke(onReturnInst, params);\n-        } catch (InvocationTargetException e) {\n-            fireThrowCallback(invoker, invocation, e.getTargetException());\n-        } catch (Throwable e) {\n-            fireThrowCallback(invoker, invocation, e);\n-        }\n-    }\n-\n-    private void fireThrowCallback(final Invoker<?> invoker, final Invocation invocation, final Throwable exception) {\n-        final AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);\n-        if (asyncMethodInfo == null) {\n-            return;\n-        }\n-\n-        final Method onthrowMethod = asyncMethodInfo.getOnthrowMethod();\n-        final Object onthrowInst = asyncMethodInfo.getOnthrowInstance();\n-\n-        //onthrow callback not configured\n-        if (onthrowMethod == null && onthrowInst == null) {\n-            return;\n-        }\n-        if (onthrowMethod == null || onthrowInst == null) {\n-            throw new IllegalStateException(\"service:\" + invoker.getUrl().getServiceKey() + \" has a onthrow callback config , but no such \" + (onthrowMethod == null ? \"method\" : \"instance\") + \" found. url:\" + invoker.getUrl());\n-        }\n-        ReflectUtils.makeAccessible(onthrowMethod);\n-        Class<?>[] rParaTypes = onthrowMethod.getParameterTypes();\n-        if (rParaTypes[0].isAssignableFrom(exception.getClass())) {\n-            try {\n-                Object[] args = invocation.getArguments();\n-                Object[] params;\n-\n-                if (rParaTypes.length > 1) {\n-                    if (rParaTypes.length == 2 && rParaTypes[1].isAssignableFrom(Object[].class)) {\n-                        params = new Object[2];\n-                        params[0] = exception;\n-                        params[1] = args;\n-                    } else {\n-                        params = new Object[args.length + 1];\n-                        params[0] = exception;\n-                        System.arraycopy(args, 0, params, 1, args.length);\n-                    }\n-                } else {\n-                    params = new Object[]{exception};\n-                }\n-                onthrowMethod.invoke(onthrowInst, params);\n-            } catch (Throwable e) {\n-                logger.error(invocation.getMethodName() + \".call back method invoke error . callback method :\" + onthrowMethod + \", url:\" + invoker.getUrl(), e);\n-            }\n-        } else {\n-            logger.error(invocation.getMethodName() + \".call back method invoke error . callback method :\" + onthrowMethod + \", url:\" + invoker.getUrl(), exception);\n-        }\n-    }\n-\n-    private AsyncMethodInfo getAsyncMethodInfo(Invoker<?> invoker, Invocation invocation) {\n-        AsyncMethodInfo asyncMethodInfo = (AsyncMethodInfo) invocation.get(ASYNC_METHOD_INFO);\n-        if (asyncMethodInfo != null) {\n-            return asyncMethodInfo;\n-        }\n-\n-        ConsumerModel consumerModel = ApplicationModel.getConsumerModel(invoker.getUrl().getServiceKey());\n-        if (consumerModel == null) {\n-            return null;\n-        }\n-\n-        String methodName = invocation.getMethodName();\n-        if (methodName.equals($INVOKE)) {\n-            methodName = (String) invocation.getArguments()[0];\n-        }\n-\n-        return consumerModel.getAsyncInfo(methodName);\n-    }\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo.filter;\r\n+\r\n+import org.apache.dubbo.common.constants.CommonConstants;\r\n+import org.apache.dubbo.common.extension.Activate;\r\n+import org.apache.dubbo.common.logger.Logger;\r\n+import org.apache.dubbo.common.logger.LoggerFactory;\r\n+import org.apache.dubbo.common.utils.ReflectUtils;\r\n+import org.apache.dubbo.rpc.Filter;\r\n+import org.apache.dubbo.rpc.Invocation;\r\n+import org.apache.dubbo.rpc.Invoker;\r\n+import org.apache.dubbo.rpc.Result;\r\n+import org.apache.dubbo.rpc.RpcException;\r\n+import org.apache.dubbo.rpc.model.ApplicationModel;\r\n+import org.apache.dubbo.rpc.model.AsyncMethodInfo;\r\n+import org.apache.dubbo.rpc.model.ConsumerModel;\r\n+\r\n+import java.lang.reflect.InvocationTargetException;\r\n+import java.lang.reflect.Method;\r\n+\r\n+import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;\r\n+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.ASYNC_METHOD_INFO;\r\n+\r\n+/**\r\n+ * EventFilter\r\n+ */\r\n+@Activate(group = CommonConstants.CONSUMER)\r\n+public class FutureFilter implements Filter, Filter.Listener {\r\n+\r\n+    protected static final Logger logger = LoggerFactory.getLogger(FutureFilter.class);\r\n+\r\n+    @Override\r\n+    public Result invoke(final Invoker<?> invoker, final Invocation invocation) throws RpcException {\r\n+        fireInvokeCallback(invoker, invocation);\r\n+        // need to configure if there's return value before the invocation in order to help invoker to judge if it's\r\n+        // necessary to return future.\r\n+        return invoker.invoke(invocation);\r\n+    }\r\n+\r\n+    @Override\r\n+    public void onResponse(Result result, Invoker<?> invoker, Invocation invocation) {\r\n+        if (result.hasException()) {\r\n+            fireThrowCallback(invoker, invocation, result.getException());\r\n+        } else {\r\n+            fireReturnCallback(invoker, invocation, result.getValue());\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {\r\n+        fireThrowCallback(invoker, invocation, t);\r\n+    }\r\n+\r\n+    private void fireInvokeCallback(final Invoker<?> invoker, final Invocation invocation) {\r\n+        final AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);\r\n+        if (asyncMethodInfo == null) {\r\n+            return;\r\n+        }\r\n+        final Method onInvokeMethod = asyncMethodInfo.getOninvokeMethod();\r\n+        final Object onInvokeInst = asyncMethodInfo.getOninvokeInstance();\r\n+\r\n+        if (onInvokeMethod == null && onInvokeInst == null) {\r\n+            return;\r\n+        }\r\n+        if (onInvokeMethod == null || onInvokeInst == null) {\r\n+            throw new IllegalStateException(\"service:\" + invoker.getUrl().getServiceKey() + \" has a oninvoke callback config , but no such \" + (onInvokeMethod == null ? \"method\" : \"instance\") + \" found. url:\" + invoker.getUrl());\r\n+        }\r\n+\r\n+        ReflectUtils.makeAccessible(onInvokeMethod);\r\n+        Object[] params = invocation.getArguments();\r\n+        try {\r\n+            onInvokeMethod.invoke(onInvokeInst, params);\r\n+        } catch (InvocationTargetException e) {\r\n+            fireThrowCallback(invoker, invocation, e.getTargetException());\r\n+        } catch (Throwable e) {\r\n+            fireThrowCallback(invoker, invocation, e);\r\n+        }\r\n+    }\r\n+\r\n+    private void fireReturnCallback(final Invoker<?> invoker, final Invocation invocation, final Object result) {\r\n+        final AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);\r\n+        if (asyncMethodInfo == null) {\r\n+            return;\r\n+        }\r\n+\r\n+        final Method onReturnMethod = asyncMethodInfo.getOnreturnMethod();\r\n+        final Object onReturnInst = asyncMethodInfo.getOnreturnInstance();\r\n+\r\n+        //not set onreturn callback\r\n+        if (onReturnMethod == null && onReturnInst == null) {\r\n+            return;\r\n+        }\r\n+\r\n+        if (onReturnMethod == null || onReturnInst == null) {\r\n+            throw new IllegalStateException(\"service:\" + invoker.getUrl().getServiceKey() + \" has a onreturn callback config , but no such \" + (onReturnMethod == null ? \"method\" : \"instance\") + \" found. url:\" + invoker.getUrl());\r\n+        }\r\n+        ReflectUtils.makeAccessible(onReturnMethod);\r\n+\r\n+        Object[] args = invocation.getArguments();\r\n+        Object[] params;\r\n+        Class<?>[] rParaTypes = onReturnMethod.getParameterTypes();\r\n+        if (rParaTypes.length > 1) {\r\n+            if (rParaTypes.length == 2 && rParaTypes[1].isAssignableFrom(Object[].class)) {\r\n+                params = new Object[2];\r\n+                params[0] = result;\r\n+                params[1] = args;\r\n+            } else {\r\n+                params = new Object[args.length + 1];\r\n+                params[0] = result;\r\n+                System.arraycopy(args, 0, params, 1, args.length);\r\n+            }\r\n+        } else {\r\n+            params = new Object[]{result};\r\n+        }\r\n+        try {\r\n+            onReturnMethod.invoke(onReturnInst, params);\r\n+        } catch (InvocationTargetException e) {\r\n+            fireThrowCallback(invoker, invocation, e.getTargetException());\r\n+        } catch (Throwable e) {\r\n+            fireThrowCallback(invoker, invocation, e);\r\n+        }\r\n+    }\r\n+\r\n+    private void fireThrowCallback(final Invoker<?> invoker, final Invocation invocation, final Throwable exception) {\r\n+        final AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);\r\n+        if (asyncMethodInfo == null) {\r\n+            return;\r\n+        }\r\n+\r\n+        final Method onthrowMethod = asyncMethodInfo.getOnthrowMethod();\r\n+        final Object onthrowInst = asyncMethodInfo.getOnthrowInstance();\r\n+\r\n+        //onthrow callback not configured\r\n+        if (onthrowMethod == null && onthrowInst == null) {\r\n+            return;\r\n+        }\r\n+        if (onthrowMethod == null || onthrowInst == null) {\r\n+            throw new IllegalStateException(\"service:\" + invoker.getUrl().getServiceKey() + \" has a onthrow callback config , but no such \" + (onthrowMethod == null ? \"method\" : \"instance\") + \" found. url:\" + invoker.getUrl());\r\n+        }\r\n+        ReflectUtils.makeAccessible(onthrowMethod);\r\n+        Class<?>[] rParaTypes = onthrowMethod.getParameterTypes();\r\n+        if (rParaTypes[0].isAssignableFrom(exception.getClass())) {\r\n+            try {\r\n+                Object[] args = invocation.getArguments();\r\n+                Object[] params;\r\n+\r\n+                if (rParaTypes.length > 1) {\r\n+                    if (rParaTypes.length == 2 && rParaTypes[1].isAssignableFrom(Object[].class)) {\r\n+                        params = new Object[2];\r\n+                        params[0] = exception;\r\n+                        params[1] = args;\r\n+                    } else {\r\n+                        params = new Object[args.length + 1];\r\n+                        params[0] = exception;\r\n+                        System.arraycopy(args, 0, params, 1, args.length);\r\n+                    }\r\n+                } else {\r\n+                    params = new Object[]{exception};\r\n+                }\r\n+                onthrowMethod.invoke(onthrowInst, params);\r\n+            } catch (Throwable e) {\r\n+                logger.error(invocation.getMethodName() + \".call back method invoke error . callback method :\" + onthrowMethod + \", url:\" + invoker.getUrl(), e);\r\n+            }\r\n+        } else {\r\n+            logger.error(invocation.getMethodName() + \".call back method invoke error . callback method :\" + onthrowMethod + \", url:\" + invoker.getUrl(), exception);\r\n+        }\r\n+    }\r\n+\r\n+    private AsyncMethodInfo getAsyncMethodInfo(Invoker<?> invoker, Invocation invocation) {\r\n+        AsyncMethodInfo asyncMethodInfo = (AsyncMethodInfo) invocation.get(ASYNC_METHOD_INFO);\r\n+        if (asyncMethodInfo != null) {\r\n+            return asyncMethodInfo;\r\n+        }\r\n+\r\n+        ConsumerModel consumerModel = ApplicationModel.getConsumerModel(invoker.getUrl().getServiceKey());\r\n+        if (consumerModel == null) {\r\n+            return null;\r\n+        }\r\n+\r\n+        String methodName = invocation.getMethodName();\r\n+        if (methodName.equals($INVOKE)) {\r\n+            methodName = (String) invocation.getArguments()[0];\r\n+        }\r\n+\r\n+        return consumerModel.getAsyncInfo(methodName);\r\n+    }\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/filter/TraceFilter.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/filter/TraceFilter.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,127 +1,127 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo.filter;\n-\n-import org.apache.dubbo.common.constants.CommonConstants;\n-import org.apache.dubbo.common.extension.Activate;\n-import org.apache.dubbo.common.logger.Logger;\n-import org.apache.dubbo.common.logger.LoggerFactory;\n-import org.apache.dubbo.common.utils.CollectionUtils;\n-import org.apache.dubbo.common.utils.ConcurrentHashSet;\n-import org.apache.dubbo.remoting.Channel;\n-import org.apache.dubbo.remoting.Constants;\n-import org.apache.dubbo.rpc.Filter;\n-import org.apache.dubbo.rpc.Invocation;\n-import org.apache.dubbo.rpc.Invoker;\n-import org.apache.dubbo.rpc.Result;\n-import org.apache.dubbo.rpc.RpcContext;\n-import org.apache.dubbo.rpc.RpcException;\n-\n-import com.alibaba.fastjson.JSON;\n-\n-import java.util.ArrayList;\n-import java.util.Set;\n-import java.util.concurrent.ConcurrentHashMap;\n-import java.util.concurrent.ConcurrentMap;\n-import java.util.concurrent.atomic.AtomicInteger;\n-\n-/**\n- * TraceFilter\n- */\n-@Activate(group = CommonConstants.PROVIDER)\n-public class TraceFilter implements Filter {\n-\n-    private static final Logger logger = LoggerFactory.getLogger(TraceFilter.class);\n-\n-    private static final String TRACE_MAX = \"trace.max\";\n-\n-    private static final String TRACE_COUNT = \"trace.count\";\n-\n-    private static final ConcurrentMap<String, Set<Channel>> TRACERS = new ConcurrentHashMap<>();\n-\n-    public static void addTracer(Class<?> type, String method, Channel channel, int max) {\n-        channel.setAttribute(TRACE_MAX, max);\n-        channel.setAttribute(TRACE_COUNT, new AtomicInteger());\n-        String key = method != null && method.length() > 0 ? type.getName() + \".\" + method : type.getName();\n-        Set<Channel> channels = TRACERS.computeIfAbsent(key, k -> new ConcurrentHashSet<>());\n-        channels.add(channel);\n-    }\n-\n-    public static void removeTracer(Class<?> type, String method, Channel channel) {\n-        channel.removeAttribute(TRACE_MAX);\n-        channel.removeAttribute(TRACE_COUNT);\n-        String key = method != null && method.length() > 0 ? type.getName() + \".\" + method : type.getName();\n-        Set<Channel> channels = TRACERS.get(key);\n-        if (channels != null) {\n-            channels.remove(channel);\n-        }\n-    }\n-\n-    @Override\n-    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {\n-        long start = System.currentTimeMillis();\n-        Result result = invoker.invoke(invocation);\n-        long end = System.currentTimeMillis();\n-        if (TRACERS.size() > 0) {\n-            String key = invoker.getInterface().getName() + \".\" + invocation.getMethodName();\n-            Set<Channel> channels = TRACERS.get(key);\n-            if (channels == null || channels.isEmpty()) {\n-                key = invoker.getInterface().getName();\n-                channels = TRACERS.get(key);\n-            }\n-            if (CollectionUtils.isNotEmpty(channels)) {\n-                for (Channel channel : new ArrayList<>(channels)) {\n-                    if (channel.isConnected()) {\n-                        try {\n-                            int max = 1;\n-                            Integer m = (Integer) channel.getAttribute(TRACE_MAX);\n-                            if (m != null) {\n-                                max = m;\n-                            }\n-                            int count = 0;\n-                            AtomicInteger c = (AtomicInteger) channel.getAttribute(TRACE_COUNT);\n-                            if (c == null) {\n-                                c = new AtomicInteger();\n-                                channel.setAttribute(TRACE_COUNT, c);\n-                            }\n-                            count = c.getAndIncrement();\n-                            if (count < max) {\n-                                String prompt = channel.getUrl().getParameter(Constants.PROMPT_KEY, Constants.DEFAULT_PROMPT);\n-                                channel.send(\"\\r\\n\" + RpcContext.getContext().getRemoteAddress() + \" -> \"\n-                                        + invoker.getInterface().getName()\n-                                        + \".\" + invocation.getMethodName()\n-                                        + \"(\" + JSON.toJSONString(invocation.getArguments()) + \")\" + \" -> \" + JSON.toJSONString(result.getValue())\n-                                        + \"\\r\\nelapsed: \" + (end - start) + \" ms.\"\n-                                        + \"\\r\\n\\r\\n\" + prompt);\n-                            }\n-                            if (count >= max - 1) {\n-                                channels.remove(channel);\n-                            }\n-                        } catch (Throwable e) {\n-                            channels.remove(channel);\n-                            logger.warn(e.getMessage(), e);\n-                        }\n-                    } else {\n-                        channels.remove(channel);\n-                    }\n-                }\n-            }\n-        }\n-        return result;\n-    }\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo.filter;\r\n+\r\n+import org.apache.dubbo.common.constants.CommonConstants;\r\n+import org.apache.dubbo.common.extension.Activate;\r\n+import org.apache.dubbo.common.logger.Logger;\r\n+import org.apache.dubbo.common.logger.LoggerFactory;\r\n+import org.apache.dubbo.common.utils.CollectionUtils;\r\n+import org.apache.dubbo.common.utils.ConcurrentHashSet;\r\n+import org.apache.dubbo.remoting.Channel;\r\n+import org.apache.dubbo.remoting.Constants;\r\n+import org.apache.dubbo.rpc.Filter;\r\n+import org.apache.dubbo.rpc.Invocation;\r\n+import org.apache.dubbo.rpc.Invoker;\r\n+import org.apache.dubbo.rpc.Result;\r\n+import org.apache.dubbo.rpc.RpcContext;\r\n+import org.apache.dubbo.rpc.RpcException;\r\n+\r\n+import com.alibaba.fastjson.JSON;\r\n+\r\n+import java.util.ArrayList;\r\n+import java.util.Set;\r\n+import java.util.concurrent.ConcurrentHashMap;\r\n+import java.util.concurrent.ConcurrentMap;\r\n+import java.util.concurrent.atomic.AtomicInteger;\r\n+\r\n+/**\r\n+ * TraceFilter\r\n+ */\r\n+@Activate(group = CommonConstants.PROVIDER)\r\n+public class TraceFilter implements Filter {\r\n+\r\n+    private static final Logger logger = LoggerFactory.getLogger(TraceFilter.class);\r\n+\r\n+    private static final String TRACE_MAX = \"trace.max\";\r\n+\r\n+    private static final String TRACE_COUNT = \"trace.count\";\r\n+\r\n+    private static final ConcurrentMap<String, Set<Channel>> TRACERS = new ConcurrentHashMap<>();\r\n+\r\n+    public static void addTracer(Class<?> type, String method, Channel channel, int max) {\r\n+        channel.setAttribute(TRACE_MAX, max);\r\n+        channel.setAttribute(TRACE_COUNT, new AtomicInteger());\r\n+        String key = method != null && method.length() > 0 ? type.getName() + \".\" + method : type.getName();\r\n+        Set<Channel> channels = TRACERS.computeIfAbsent(key, k -> new ConcurrentHashSet<>());\r\n+        channels.add(channel);\r\n+    }\r\n+\r\n+    public static void removeTracer(Class<?> type, String method, Channel channel) {\r\n+        channel.removeAttribute(TRACE_MAX);\r\n+        channel.removeAttribute(TRACE_COUNT);\r\n+        String key = method != null && method.length() > 0 ? type.getName() + \".\" + method : type.getName();\r\n+        Set<Channel> channels = TRACERS.get(key);\r\n+        if (channels != null) {\r\n+            channels.remove(channel);\r\n+        }\r\n+    }\r\n+\r\n+    @Override\r\n+    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {\r\n+        long start = System.currentTimeMillis();\r\n+        Result result = invoker.invoke(invocation);\r\n+        long end = System.currentTimeMillis();\r\n+        if (TRACERS.size() > 0) {\r\n+            String key = invoker.getInterface().getName() + \".\" + invocation.getMethodName();\r\n+            Set<Channel> channels = TRACERS.get(key);\r\n+            if (channels == null || channels.isEmpty()) {\r\n+                key = invoker.getInterface().getName();\r\n+                channels = TRACERS.get(key);\r\n+            }\r\n+            if (CollectionUtils.isNotEmpty(channels)) {\r\n+                for (Channel channel : new ArrayList<>(channels)) {\r\n+                    if (channel.isConnected()) {\r\n+                        try {\r\n+                            int max = 1;\r\n+                            Integer m = (Integer) channel.getAttribute(TRACE_MAX);\r\n+                            if (m != null) {\r\n+                                max = m;\r\n+                            }\r\n+                            int count = 0;\r\n+                            AtomicInteger c = (AtomicInteger) channel.getAttribute(TRACE_COUNT);\r\n+                            if (c == null) {\r\n+                                c = new AtomicInteger();\r\n+                                channel.setAttribute(TRACE_COUNT, c);\r\n+                            }\r\n+                            count = c.getAndIncrement();\r\n+                            if (count < max) {\r\n+                                String prompt = channel.getUrl().getParameter(Constants.PROMPT_KEY, Constants.DEFAULT_PROMPT);\r\n+                                channel.send(\"\\r\\n\" + RpcContext.getContext().getRemoteAddress() + \" -> \"\r\n+                                        + invoker.getInterface().getName()\r\n+                                        + \".\" + invocation.getMethodName()\r\n+                                        + \"(\" + JSON.toJSONString(invocation.getArguments()) + \")\" + \" -> \" + JSON.toJSONString(result.getValue())\r\n+                                        + \"\\r\\nelapsed: \" + (end - start) + \" ms.\"\r\n+                                        + \"\\r\\n\\r\\n\" + prompt);\r\n+                            }\r\n+                            if (count >= max - 1) {\r\n+                                channels.remove(channel);\r\n+                            }\r\n+                        } catch (Throwable e) {\r\n+                            channels.remove(channel);\r\n+                            logger.warn(e.getMessage(), e);\r\n+                        }\r\n+                    } else {\r\n+                        channels.remove(channel);\r\n+                    }\r\n+                }\r\n+            }\r\n+        }\r\n+        return result;\r\n+    }\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/status/ServerStatusChecker.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/status/ServerStatusChecker.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,61 +1,61 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo.status;\n-\n-import org.apache.dubbo.common.extension.Activate;\n-import org.apache.dubbo.common.status.Status;\n-import org.apache.dubbo.common.status.StatusChecker;\n-import org.apache.dubbo.remoting.RemotingServer;\n-import org.apache.dubbo.rpc.ProtocolServer;\n-import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;\n-\n-import java.util.List;\n-\n-/**\n- * ServerStatusChecker\n- */\n-@Activate\n-public class ServerStatusChecker implements StatusChecker {\n-\n-    @Override\n-    public Status check() {\n-        List<ProtocolServer> servers = DubboProtocol.getDubboProtocol().getServers();\n-        if (servers == null || servers.isEmpty()) {\n-            return new Status(Status.Level.UNKNOWN);\n-        }\n-        Status.Level level = Status.Level.OK;\n-        StringBuilder buf = new StringBuilder();\n-        for (ProtocolServer protocolServer : servers) {\n-            RemotingServer server = protocolServer.getRemotingServer();\n-            if (!server.isBound()) {\n-                level = Status.Level.ERROR;\n-                buf.setLength(0);\n-                buf.append(server.getLocalAddress());\n-                break;\n-            }\n-            if (buf.length() > 0) {\n-                buf.append(\",\");\n-            }\n-            buf.append(server.getLocalAddress());\n-            buf.append(\"(clients:\");\n-            buf.append(server.getChannels().size());\n-            buf.append(\")\");\n-        }\n-        return new Status(level, buf.toString());\n-    }\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo.status;\r\n+\r\n+import org.apache.dubbo.common.extension.Activate;\r\n+import org.apache.dubbo.common.status.Status;\r\n+import org.apache.dubbo.common.status.StatusChecker;\r\n+import org.apache.dubbo.remoting.RemotingServer;\r\n+import org.apache.dubbo.rpc.ProtocolServer;\r\n+import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;\r\n+\r\n+import java.util.List;\r\n+\r\n+/**\r\n+ * ServerStatusChecker\r\n+ */\r\n+@Activate\r\n+public class ServerStatusChecker implements StatusChecker {\r\n+\r\n+    @Override\r\n+    public Status check() {\r\n+        List<ProtocolServer> servers = DubboProtocol.getDubboProtocol().getServers();\r\n+        if (servers == null || servers.isEmpty()) {\r\n+            return new Status(Status.Level.UNKNOWN);\r\n+        }\r\n+        Status.Level level = Status.Level.OK;\r\n+        StringBuilder buf = new StringBuilder();\r\n+        for (ProtocolServer protocolServer : servers) {\r\n+            RemotingServer server = protocolServer.getRemotingServer();\r\n+            if (!server.isBound()) {\r\n+                level = Status.Level.ERROR;\r\n+                buf.setLength(0);\r\n+                buf.append(server.getLocalAddress());\r\n+                break;\r\n+            }\r\n+            if (buf.length() > 0) {\r\n+                buf.append(\",\");\r\n+            }\r\n+            buf.append(server.getLocalAddress());\r\n+            buf.append(\"(clients:\");\r\n+            buf.append(server.getChannels().size());\r\n+            buf.append(\")\");\r\n+        }\r\n+        return new Status(level, buf.toString());\r\n+    }\r\n+\r\n+}\r\n"}, {"source1": "org/apache/dubbo/rpc/protocol/dubbo/status/ThreadPoolStatusChecker.java", "source2": "org/apache/dubbo/rpc/protocol/dubbo/status/ThreadPoolStatusChecker.java", "comments": ["Ordering differences only"], "unified_diff": "@@ -1,67 +1,67 @@\n-/*\n- * Licensed to the Apache Software Foundation (ASF) under one or more\n- * contributor license agreements.  See the NOTICE file distributed with\n- * this work for additional information regarding copyright ownership.\n- * The ASF licenses this file to You under the Apache License, Version 2.0\n- * (the \"License\"); you may not use this file except in compliance with\n- * the License.  You may obtain a copy of the License at\n- *\n- *     http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-package org.apache.dubbo.rpc.protocol.dubbo.status;\n-\n-import org.apache.dubbo.common.constants.CommonConstants;\n-import org.apache.dubbo.common.extension.Activate;\n-import org.apache.dubbo.common.extension.ExtensionLoader;\n-import org.apache.dubbo.common.status.Status;\n-import org.apache.dubbo.common.status.StatusChecker;\n-import org.apache.dubbo.common.store.DataStore;\n-\n-import java.util.Map;\n-import java.util.concurrent.ExecutorService;\n-import java.util.concurrent.ThreadPoolExecutor;\n-\n-/**\n- * ThreadPoolStatusChecker\n- */\n-@Activate\n-public class ThreadPoolStatusChecker implements StatusChecker {\n-\n-    @Override\n-    public Status check() {\n-        DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();\n-        Map<String, Object> executors = dataStore.get(CommonConstants.EXECUTOR_SERVICE_COMPONENT_KEY);\n-\n-        StringBuilder msg = new StringBuilder();\n-        Status.Level level = Status.Level.OK;\n-        for (Map.Entry<String, Object> entry : executors.entrySet()) {\n-            String port = entry.getKey();\n-            ExecutorService executor = (ExecutorService) entry.getValue();\n-\n-            if (executor instanceof ThreadPoolExecutor) {\n-                ThreadPoolExecutor tp = (ThreadPoolExecutor) executor;\n-                boolean ok = tp.getActiveCount() < tp.getMaximumPoolSize() - 1;\n-                Status.Level lvl = Status.Level.OK;\n-                if (!ok) {\n-                    level = Status.Level.WARN;\n-                    lvl = Status.Level.WARN;\n-                }\n-\n-                if (msg.length() > 0) {\n-                    msg.append(\";\");\n-                }\n-                msg.append(\"Pool status:\").append(lvl).append(\", max:\").append(tp.getMaximumPoolSize()).append(\", core:\")\n-                        .append(tp.getCorePoolSize()).append(\", largest:\").append(tp.getLargestPoolSize()).append(\", active:\")\n-                        .append(tp.getActiveCount()).append(\", task:\").append(tp.getTaskCount()).append(\", service port: \").append(port);\n-            }\n-        }\n-        return msg.length() == 0 ? new Status(Status.Level.UNKNOWN) : new Status(level, msg.toString());\n-    }\n-\n-}\n+/*\r\n+ * Licensed to the Apache Software Foundation (ASF) under one or more\r\n+ * contributor license agreements.  See the NOTICE file distributed with\r\n+ * this work for additional information regarding copyright ownership.\r\n+ * The ASF licenses this file to You under the Apache License, Version 2.0\r\n+ * (the \"License\"); you may not use this file except in compliance with\r\n+ * the License.  You may obtain a copy of the License at\r\n+ *\r\n+ *     http://www.apache.org/licenses/LICENSE-2.0\r\n+ *\r\n+ * Unless required by applicable law or agreed to in writing, software\r\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n+ * See the License for the specific language governing permissions and\r\n+ * limitations under the License.\r\n+ */\r\n+package org.apache.dubbo.rpc.protocol.dubbo.status;\r\n+\r\n+import org.apache.dubbo.common.constants.CommonConstants;\r\n+import org.apache.dubbo.common.extension.Activate;\r\n+import org.apache.dubbo.common.extension.ExtensionLoader;\r\n+import org.apache.dubbo.common.status.Status;\r\n+import org.apache.dubbo.common.status.StatusChecker;\r\n+import org.apache.dubbo.common.store.DataStore;\r\n+\r\n+import java.util.Map;\r\n+import java.util.concurrent.ExecutorService;\r\n+import java.util.concurrent.ThreadPoolExecutor;\r\n+\r\n+/**\r\n+ * ThreadPoolStatusChecker\r\n+ */\r\n+@Activate\r\n+public class ThreadPoolStatusChecker implements StatusChecker {\r\n+\r\n+    @Override\r\n+    public Status check() {\r\n+        DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();\r\n+        Map<String, Object> executors = dataStore.get(CommonConstants.EXECUTOR_SERVICE_COMPONENT_KEY);\r\n+\r\n+        StringBuilder msg = new StringBuilder();\r\n+        Status.Level level = Status.Level.OK;\r\n+        for (Map.Entry<String, Object> entry : executors.entrySet()) {\r\n+            String port = entry.getKey();\r\n+            ExecutorService executor = (ExecutorService) entry.getValue();\r\n+\r\n+            if (executor instanceof ThreadPoolExecutor) {\r\n+                ThreadPoolExecutor tp = (ThreadPoolExecutor) executor;\r\n+                boolean ok = tp.getActiveCount() < tp.getMaximumPoolSize() - 1;\r\n+                Status.Level lvl = Status.Level.OK;\r\n+                if (!ok) {\r\n+                    level = Status.Level.WARN;\r\n+                    lvl = Status.Level.WARN;\r\n+                }\r\n+\r\n+                if (msg.length() > 0) {\r\n+                    msg.append(\";\");\r\n+                }\r\n+                msg.append(\"Pool status:\").append(lvl).append(\", max:\").append(tp.getMaximumPoolSize()).append(\", core:\")\r\n+                        .append(tp.getCorePoolSize()).append(\", largest:\").append(tp.getLargestPoolSize()).append(\", active:\")\r\n+                        .append(tp.getActiveCount()).append(\", task:\").append(tp.getTaskCount()).append(\", service port: \").append(port);\r\n+            }\r\n+        }\r\n+        return msg.length() == 0 ? new Status(Status.Level.UNKNOWN) : new Status(level, msg.toString());\r\n+    }\r\n+\r\n+}\r\n"}, {"source1": "META-INF/maven/org.apache.dubbo/dubbo-rpc-dubbo/pom.xml", "source2": "META-INF/maven/org.apache.dubbo/dubbo-rpc-dubbo/pom.xml", "comments": ["Format-specific differences are supported for XML files but no file-specific differences were detected; falling back to a binary diff. file(1) reports: XML 1.0 document, ASCII text, with CRLF line terminators"], "has_internal_linenos": true, "unified_diff": "@@ -1,252 +1,245 @@\n 00000000: 3c3f 786d 6c20 7665 7273 696f 6e3d 2231  <?xml version=\"1\n 00000010: 2e30 2220 656e 636f 6469 6e67 3d22 5554  .0\" encoding=\"UT\n-00000020: 462d 3822 3f3e 0d0a 3c21 2d2d 0d0a 2020  F-8\"?>..<!--..  \n-00000030: 4c69 6365 6e73 6564 2074 6f20 7468 6520  Licensed to the \n-00000040: 4170 6163 6865 2053 6f66 7477 6172 6520  Apache Software \n-00000050: 466f 756e 6461 7469 6f6e 2028 4153 4629  Foundation (ASF)\n-00000060: 2075 6e64 6572 206f 6e65 206f 7220 6d6f   under one or mo\n-00000070: 7265 0d0a 2020 636f 6e74 7269 6275 746f  re..  contributo\n-00000080: 7220 6c69 6365 6e73 6520 6167 7265 656d  r license agreem\n-00000090: 656e 7473 2e20 2053 6565 2074 6865 204e  ents.  See the N\n-000000a0: 4f54 4943 4520 6669 6c65 2064 6973 7472  OTICE file distr\n-000000b0: 6962 7574 6564 2077 6974 680d 0a20 2074  ibuted with..  t\n-000000c0: 6869 7320 776f 726b 2066 6f72 2061 6464  his work for add\n-000000d0: 6974 696f 6e61 6c20 696e 666f 726d 6174  itional informat\n-000000e0: 696f 6e20 7265 6761 7264 696e 6720 636f  ion regarding co\n-000000f0: 7079 7269 6768 7420 6f77 6e65 7273 6869  pyright ownershi\n-00000100: 702e 0d0a 2020 5468 6520 4153 4620 6c69  p...  The ASF li\n-00000110: 6365 6e73 6573 2074 6869 7320 6669 6c65  censes this file\n-00000120: 2074 6f20 596f 7520 756e 6465 7220 7468   to You under th\n-00000130: 6520 4170 6163 6865 204c 6963 656e 7365  e Apache License\n-00000140: 2c20 5665 7273 696f 6e20 322e 300d 0a20  , Version 2.0.. \n-00000150: 2028 7468 6520 224c 6963 656e 7365 2229   (the \"License\")\n-00000160: 3b20 796f 7520 6d61 7920 6e6f 7420 7573  ; you may not us\n-00000170: 6520 7468 6973 2066 696c 6520 6578 6365  e this file exce\n-00000180: 7074 2069 6e20 636f 6d70 6c69 616e 6365  pt in compliance\n-00000190: 2077 6974 680d 0a20 2074 6865 204c 6963   with..  the Lic\n-000001a0: 656e 7365 2e20 2059 6f75 206d 6179 206f  ense.  You may o\n-000001b0: 6274 6169 6e20 6120 636f 7079 206f 6620  btain a copy of \n-000001c0: 7468 6520 4c69 6365 6e73 6520 6174 0d0a  the License at..\n-000001d0: 0d0a 2020 2020 2020 6874 7470 3a2f 2f77  ..      http://w\n-000001e0: 7777 2e61 7061 6368 652e 6f72 672f 6c69  ww.apache.org/li\n-000001f0: 6365 6e73 6573 2f4c 4943 454e 5345 2d32  censes/LICENSE-2\n-00000200: 2e30 0d0a 0d0a 2020 556e 6c65 7373 2072  .0....  Unless r\n-00000210: 6571 7569 7265 6420 6279 2061 7070 6c69  equired by appli\n-00000220: 6361 626c 6520 6c61 7720 6f72 2061 6772  cable law or agr\n-00000230: 6565 6420 746f 2069 6e20 7772 6974 696e  eed to in writin\n-00000240: 672c 2073 6f66 7477 6172 650d 0a20 2064  g, software..  d\n-00000250: 6973 7472 6962 7574 6564 2075 6e64 6572  istributed under\n-00000260: 2074 6865 204c 6963 656e 7365 2069 7320   the License is \n-00000270: 6469 7374 7269 6275 7465 6420 6f6e 2061  distributed on a\n-00000280: 6e20 2241 5320 4953 2220 4241 5349 532c  n \"AS IS\" BASIS,\n-00000290: 0d0a 2020 5749 5448 4f55 5420 5741 5252  ..  WITHOUT WARR\n-000002a0: 414e 5449 4553 204f 5220 434f 4e44 4954  ANTIES OR CONDIT\n-000002b0: 494f 4e53 204f 4620 414e 5920 4b49 4e44  IONS OF ANY KIND\n-000002c0: 2c20 6569 7468 6572 2065 7870 7265 7373  , either express\n-000002d0: 206f 7220 696d 706c 6965 642e 0d0a 2020   or implied...  \n-000002e0: 5365 6520 7468 6520 4c69 6365 6e73 6520  See the License \n-000002f0: 666f 7220 7468 6520 7370 6563 6966 6963  for the specific\n-00000300: 206c 616e 6775 6167 6520 676f 7665 726e   language govern\n-00000310: 696e 6720 7065 726d 6973 7369 6f6e 7320  ing permissions \n-00000320: 616e 640d 0a20 206c 696d 6974 6174 696f  and..  limitatio\n-00000330: 6e73 2075 6e64 6572 2074 6865 204c 6963  ns under the Lic\n-00000340: 656e 7365 2e0d 0a20 202d 2d3e 0d0a 3c70  ense...  -->..<p\n-00000350: 726f 6a65 6374 2078 7369 3a73 6368 656d  roject xsi:schem\n-00000360: 614c 6f63 6174 696f 6e3d 2268 7474 703a  aLocation=\"http:\n-00000370: 2f2f 6d61 7665 6e2e 6170 6163 6865 2e6f  //maven.apache.o\n-00000380: 7267 2f50 4f4d 2f34 2e30 2e30 2068 7474  rg/POM/4.0.0 htt\n-00000390: 7073 3a2f 2f6d 6176 656e 2e61 7061 6368  ps://maven.apach\n-000003a0: 652e 6f72 672f 7873 642f 6d61 7665 6e2d  e.org/xsd/maven-\n-000003b0: 342e 302e 302e 7873 6422 2078 6d6c 6e73  4.0.0.xsd\" xmlns\n-000003c0: 3d22 6874 7470 3a2f 2f6d 6176 656e 2e61  =\"http://maven.a\n-000003d0: 7061 6368 652e 6f72 672f 504f 4d2f 342e  pache.org/POM/4.\n-000003e0: 302e 3022 0d0a 2020 2020 786d 6c6e 733a  0.0\"..    xmlns:\n-000003f0: 7873 693d 2268 7474 703a 2f2f 7777 772e  xsi=\"http://www.\n-00000400: 7733 2e6f 7267 2f32 3030 312f 584d 4c53  w3.org/2001/XMLS\n-00000410: 6368 656d 612d 696e 7374 616e 6365 223e  chema-instance\">\n-00000420: 0d0a 2020 3c6d 6f64 656c 5665 7273 696f  ..  <modelVersio\n-00000430: 6e3e 342e 302e 303c 2f6d 6f64 656c 5665  n>4.0.0</modelVe\n-00000440: 7273 696f 6e3e 0d0a 2020 3c70 6172 656e  rsion>..  <paren\n-00000450: 743e 0d0a 2020 2020 3c67 726f 7570 4964  t>..    <groupId\n-00000460: 3e6f 7267 2e61 7061 6368 652e 6475 6262  >org.apache.dubb\n-00000470: 6f3c 2f67 726f 7570 4964 3e0d 0a20 2020  o</groupId>..   \n-00000480: 203c 6172 7469 6661 6374 4964 3e64 7562   <artifactId>dub\n-00000490: 626f 2d72 7063 3c2f 6172 7469 6661 6374  bo-rpc</artifact\n-000004a0: 4964 3e0d 0a20 2020 203c 7665 7273 696f  Id>..    <versio\n-000004b0: 6e3e 322e 372e 3130 3c2f 7665 7273 696f  n>2.7.10</versio\n-000004c0: 6e3e 0d0a 2020 3c2f 7061 7265 6e74 3e0d  n>..  </parent>.\n-000004d0: 0a20 203c 6772 6f75 7049 643e 6f72 672e  .  <groupId>org.\n-000004e0: 6170 6163 6865 2e64 7562 626f 3c2f 6772  apache.dubbo</gr\n-000004f0: 6f75 7049 643e 0d0a 2020 3c61 7274 6966  oupId>..  <artif\n-00000500: 6163 7449 643e 6475 6262 6f2d 7270 632d  actId>dubbo-rpc-\n-00000510: 6475 6262 6f3c 2f61 7274 6966 6163 7449  dubbo</artifactI\n-00000520: 643e 0d0a 2020 3c76 6572 7369 6f6e 3e32  d>..  <version>2\n-00000530: 2e37 2e31 303c 2f76 6572 7369 6f6e 3e0d  .7.10</version>.\n-00000540: 0a20 203c 6e61 6d65 3e24 7b70 726f 6a65  .  <name>${proje\n-00000550: 6374 2e61 7274 6966 6163 7449 647d 3c2f  ct.artifactId}</\n-00000560: 6e61 6d65 3e0d 0a20 203c 6465 7363 7269  name>..  <descri\n-00000570: 7074 696f 6e3e 5468 6520 6465 6661 756c  ption>The defaul\n-00000580: 7420 7270 6320 6d6f 6475 6c65 206f 6620  t rpc module of \n-00000590: 6475 6262 6f20 7072 6f6a 6563 743c 2f64  dubbo project</d\n-000005a0: 6573 6372 6970 7469 6f6e 3e0d 0a20 203c  escription>..  <\n-000005b0: 6c69 6365 6e73 6573 3e0d 0a20 2020 203c  licenses>..    <\n-000005c0: 6c69 6365 6e73 653e 0d0a 2020 2020 2020  license>..      \n-000005d0: 3c6e 616d 653e 4170 6163 6865 204c 6963  <name>Apache Lic\n-000005e0: 656e 7365 2c20 5665 7273 696f 6e20 322e  ense, Version 2.\n-000005f0: 303c 2f6e 616d 653e 0d0a 2020 2020 2020  0</name>..      \n-00000600: 3c75 726c 3e68 7474 703a 2f2f 7777 772e  <url>http://www.\n-00000610: 6170 6163 6865 2e6f 7267 2f6c 6963 656e  apache.org/licen\n-00000620: 7365 732f 4c49 4345 4e53 452d 322e 303c  ses/LICENSE-2.0<\n-00000630: 2f75 726c 3e0d 0a20 2020 2020 203c 6469  /url>..      <di\n-00000640: 7374 7269 6275 7469 6f6e 3e72 6570 6f3c  stribution>repo<\n-00000650: 2f64 6973 7472 6962 7574 696f 6e3e 0d0a  /distribution>..\n-00000660: 2020 2020 3c2f 6c69 6365 6e73 653e 0d0a      </license>..\n-00000670: 2020 3c2f 6c69 6365 6e73 6573 3e0d 0a20    </licenses>.. \n-00000680: 203c 7072 6f70 6572 7469 6573 3e0d 0a20   <properties>.. \n-00000690: 2020 203c 736b 6970 5f6d 6176 656e 5f64     <skip_maven_d\n-000006a0: 6570 6c6f 793e 6661 6c73 653c 2f73 6b69  eploy>false</ski\n-000006b0: 705f 6d61 7665 6e5f 6465 706c 6f79 3e0d  p_maven_deploy>.\n-000006c0: 0a20 203c 2f70 726f 7065 7274 6965 733e  .  </properties>\n-000006d0: 0d0a 2020 3c64 6570 656e 6465 6e63 6965  ..  <dependencie\n-000006e0: 733e 0d0a 2020 2020 3c64 6570 656e 6465  s>..    <depende\n-000006f0: 6e63 793e 0d0a 2020 2020 2020 3c67 726f  ncy>..      <gro\n-00000700: 7570 4964 3e6f 7267 2e61 7061 6368 652e  upId>org.apache.\n-00000710: 6475 6262 6f3c 2f67 726f 7570 4964 3e0d  dubbo</groupId>.\n-00000720: 0a20 2020 2020 203c 6172 7469 6661 6374  .      <artifact\n-00000730: 4964 3e64 7562 626f 2d72 7063 2d61 7069  Id>dubbo-rpc-api\n-00000740: 3c2f 6172 7469 6661 6374 4964 3e0d 0a20  </artifactId>.. \n-00000750: 2020 2020 203c 7665 7273 696f 6e3e 247b       <version>${\n-00000760: 7072 6f6a 6563 742e 7061 7265 6e74 2e76  project.parent.v\n-00000770: 6572 7369 6f6e 7d3c 2f76 6572 7369 6f6e  ersion}</version\n-00000780: 3e0d 0a20 2020 203c 2f64 6570 656e 6465  >..    </depende\n-00000790: 6e63 793e 0d0a 2020 2020 3c64 6570 656e  ncy>..    <depen\n-000007a0: 6465 6e63 793e 0d0a 2020 2020 2020 3c67  dency>..      <g\n-000007b0: 726f 7570 4964 3e6f 7267 2e61 7061 6368  roupId>org.apach\n-000007c0: 652e 6475 6262 6f3c 2f67 726f 7570 4964  e.dubbo</groupId\n-000007d0: 3e0d 0a20 2020 2020 203c 6172 7469 6661  >..      <artifa\n-000007e0: 6374 4964 3e64 7562 626f 2d72 656d 6f74  ctId>dubbo-remot\n-000007f0: 696e 672d 6170 693c 2f61 7274 6966 6163  ing-api</artifac\n-00000800: 7449 643e 0d0a 2020 2020 2020 3c76 6572  tId>..      <ver\n-00000810: 7369 6f6e 3e24 7b70 726f 6a65 6374 2e70  sion>${project.p\n-00000820: 6172 656e 742e 7665 7273 696f 6e7d 3c2f  arent.version}</\n-00000830: 7665 7273 696f 6e3e 0d0a 2020 2020 3c2f  version>..    </\n-00000840: 6465 7065 6e64 656e 6379 3e0d 0a20 2020  dependency>..   \n-00000850: 203c 6465 7065 6e64 656e 6379 3e0d 0a20   <dependency>.. \n-00000860: 2020 2020 203c 6772 6f75 7049 643e 6f72       <groupId>or\n-00000870: 672e 6170 6163 6865 2e64 7562 626f 3c2f  g.apache.dubbo</\n-00000880: 6772 6f75 7049 643e 0d0a 2020 2020 2020  groupId>..      \n-00000890: 3c61 7274 6966 6163 7449 643e 6475 6262  <artifactId>dubb\n-000008a0: 6f2d 636c 7573 7465 723c 2f61 7274 6966  o-cluster</artif\n-000008b0: 6163 7449 643e 0d0a 2020 2020 2020 3c76  actId>..      <v\n-000008c0: 6572 7369 6f6e 3e24 7b70 726f 6a65 6374  ersion>${project\n-000008d0: 2e70 6172 656e 742e 7665 7273 696f 6e7d  .parent.version}\n-000008e0: 3c2f 7665 7273 696f 6e3e 0d0a 2020 2020  </version>..    \n-000008f0: 3c2f 6465 7065 6e64 656e 6379 3e0d 0a20  </dependency>.. \n-00000900: 2020 203c 6465 7065 6e64 656e 6379 3e0d     <dependency>.\n-00000910: 0a20 2020 2020 203c 6772 6f75 7049 643e  .      <groupId>\n-00000920: 6f72 672e 6170 6163 6865 2e64 7562 626f  org.apache.dubbo\n-00000930: 3c2f 6772 6f75 7049 643e 0d0a 2020 2020  </groupId>..    \n-00000940: 2020 3c61 7274 6966 6163 7449 643e 6475    <artifactId>du\n-00000950: 6262 6f2d 7265 6d6f 7469 6e67 2d6e 6574  bbo-remoting-net\n-00000960: 7479 343c 2f61 7274 6966 6163 7449 643e  ty4</artifactId>\n-00000970: 0d0a 2020 2020 2020 3c76 6572 7369 6f6e  ..      <version\n-00000980: 3e24 7b70 726f 6a65 6374 2e70 6172 656e  >${project.paren\n-00000990: 742e 7665 7273 696f 6e7d 3c2f 7665 7273  t.version}</vers\n-000009a0: 696f 6e3e 0d0a 2020 2020 2020 3c73 636f  ion>..      <sco\n-000009b0: 7065 3e74 6573 743c 2f73 636f 7065 3e0d  pe>test</scope>.\n-000009c0: 0a20 2020 203c 2f64 6570 656e 6465 6e63  .    </dependenc\n-000009d0: 793e 0d0a 2020 2020 3c64 6570 656e 6465  y>..    <depende\n-000009e0: 6e63 793e 0d0a 2020 2020 2020 3c67 726f  ncy>..      <gro\n-000009f0: 7570 4964 3e6f 7267 2e61 7061 6368 652e  upId>org.apache.\n-00000a00: 6475 6262 6f3c 2f67 726f 7570 4964 3e0d  dubbo</groupId>.\n-00000a10: 0a20 2020 2020 203c 6172 7469 6661 6374  .      <artifact\n-00000a20: 4964 3e64 7562 626f 2d72 656d 6f74 696e  Id>dubbo-remotin\n-00000a30: 672d 6d69 6e61 3c2f 6172 7469 6661 6374  g-mina</artifact\n-00000a40: 4964 3e0d 0a20 2020 2020 203c 7665 7273  Id>..      <vers\n-00000a50: 696f 6e3e 247b 7072 6f6a 6563 742e 7061  ion>${project.pa\n-00000a60: 7265 6e74 2e76 6572 7369 6f6e 7d3c 2f76  rent.version}</v\n-00000a70: 6572 7369 6f6e 3e0d 0a20 2020 2020 203c  ersion>..      <\n-00000a80: 7363 6f70 653e 7465 7374 3c2f 7363 6f70  scope>test</scop\n-00000a90: 653e 0d0a 2020 2020 3c2f 6465 7065 6e64  e>..    </depend\n-00000aa0: 656e 6379 3e0d 0a20 2020 203c 6465 7065  ency>..    <depe\n-00000ab0: 6e64 656e 6379 3e0d 0a20 2020 2020 203c  ndency>..      <\n-00000ac0: 6772 6f75 7049 643e 696f 2e6e 6574 7479  groupId>io.netty\n-00000ad0: 3c2f 6772 6f75 7049 643e 0d0a 2020 2020  </groupId>..    \n-00000ae0: 2020 3c61 7274 6966 6163 7449 643e 6e65    <artifactId>ne\n-00000af0: 7474 792d 616c 6c3c 2f61 7274 6966 6163  tty-all</artifac\n-00000b00: 7449 643e 0d0a 2020 2020 2020 3c73 636f  tId>..      <sco\n-00000b10: 7065 3e74 6573 743c 2f73 636f 7065 3e0d  pe>test</scope>.\n-00000b20: 0a20 2020 203c 2f64 6570 656e 6465 6e63  .    </dependenc\n-00000b30: 793e 0d0a 2020 2020 3c64 6570 656e 6465  y>..    <depende\n-00000b40: 6e63 793e 0d0a 2020 2020 2020 3c67 726f  ncy>..      <gro\n-00000b50: 7570 4964 3e6f 7267 2e61 7061 6368 652e  upId>org.apache.\n-00000b60: 6475 6262 6f3c 2f67 726f 7570 4964 3e0d  dubbo</groupId>.\n-00000b70: 0a20 2020 2020 203c 6172 7469 6661 6374  .      <artifact\n-00000b80: 4964 3e64 7562 626f 2d73 6572 6961 6c69  Id>dubbo-seriali\n-00000b90: 7a61 7469 6f6e 2d68 6573 7369 616e 323c  zation-hessian2<\n-00000ba0: 2f61 7274 6966 6163 7449 643e 0d0a 2020  /artifactId>..  \n-00000bb0: 2020 2020 3c76 6572 7369 6f6e 3e24 7b70      <version>${p\n-00000bc0: 726f 6a65 6374 2e70 6172 656e 742e 7665  roject.parent.ve\n-00000bd0: 7273 696f 6e7d 3c2f 7665 7273 696f 6e3e  rsion}</version>\n-00000be0: 0d0a 2020 2020 2020 3c73 636f 7065 3e74  ..      <scope>t\n-00000bf0: 6573 743c 2f73 636f 7065 3e0d 0a20 2020  est</scope>..   \n-00000c00: 203c 2f64 6570 656e 6465 6e63 793e 0d0a   </dependency>..\n-00000c10: 2020 2020 3c64 6570 656e 6465 6e63 793e      <dependency>\n-00000c20: 0d0a 2020 2020 2020 3c67 726f 7570 4964  ..      <groupId\n-00000c30: 3e6f 7267 2e61 7061 6368 652e 6475 6262  >org.apache.dubb\n-00000c40: 6f3c 2f67 726f 7570 4964 3e0d 0a20 2020  o</groupId>..   \n-00000c50: 2020 203c 6172 7469 6661 6374 4964 3e64     <artifactId>d\n-00000c60: 7562 626f 2d73 6572 6961 6c69 7a61 7469  ubbo-serializati\n-00000c70: 6f6e 2d6a 646b 3c2f 6172 7469 6661 6374  on-jdk</artifact\n-00000c80: 4964 3e0d 0a20 2020 2020 203c 7665 7273  Id>..      <vers\n-00000c90: 696f 6e3e 247b 7072 6f6a 6563 742e 7061  ion>${project.pa\n-00000ca0: 7265 6e74 2e76 6572 7369 6f6e 7d3c 2f76  rent.version}</v\n-00000cb0: 6572 7369 6f6e 3e0d 0a20 2020 2020 203c  ersion>..      <\n-00000cc0: 7363 6f70 653e 7465 7374 3c2f 7363 6f70  scope>test</scop\n-00000cd0: 653e 0d0a 2020 2020 3c2f 6465 7065 6e64  e>..    </depend\n-00000ce0: 656e 6379 3e0d 0a20 2020 203c 6465 7065  ency>..    <depe\n-00000cf0: 6e64 656e 6379 3e0d 0a20 2020 2020 203c  ndency>..      <\n-00000d00: 6772 6f75 7049 643e 6a61 7661 782e 7661  groupId>javax.va\n-00000d10: 6c69 6461 7469 6f6e 3c2f 6772 6f75 7049  lidation</groupI\n-00000d20: 643e 0d0a 2020 2020 2020 3c61 7274 6966  d>..      <artif\n-00000d30: 6163 7449 643e 7661 6c69 6461 7469 6f6e  actId>validation\n-00000d40: 2d61 7069 3c2f 6172 7469 6661 6374 4964  -api</artifactId\n-00000d50: 3e0d 0a20 2020 2020 203c 7363 6f70 653e  >..      <scope>\n-00000d60: 7465 7374 3c2f 7363 6f70 653e 0d0a 2020  test</scope>..  \n-00000d70: 2020 3c2f 6465 7065 6e64 656e 6379 3e0d    </dependency>.\n-00000d80: 0a20 2020 203c 6465 7065 6e64 656e 6379  .    <dependency\n-00000d90: 3e0d 0a20 2020 2020 203c 6772 6f75 7049  >..      <groupI\n-00000da0: 643e 6f72 672e 6869 6265 726e 6174 653c  d>org.hibernate<\n-00000db0: 2f67 726f 7570 4964 3e0d 0a20 2020 2020  /groupId>..     \n-00000dc0: 203c 6172 7469 6661 6374 4964 3e68 6962   <artifactId>hib\n-00000dd0: 6572 6e61 7465 2d76 616c 6964 6174 6f72  ernate-validator\n-00000de0: 3c2f 6172 7469 6661 6374 4964 3e0d 0a20  </artifactId>.. \n-00000df0: 2020 2020 203c 7363 6f70 653e 7465 7374       <scope>test\n-00000e00: 3c2f 7363 6f70 653e 0d0a 2020 2020 3c2f  </scope>..    </\n-00000e10: 6465 7065 6e64 656e 6379 3e0d 0a20 2020  dependency>..   \n-00000e20: 203c 6465 7065 6e64 656e 6379 3e0d 0a20   <dependency>.. \n-00000e30: 2020 2020 203c 6772 6f75 7049 643e 6f72       <groupId>or\n-00000e40: 672e 676c 6173 7366 6973 683c 2f67 726f  g.glassfish</gro\n-00000e50: 7570 4964 3e0d 0a20 2020 2020 203c 6172  upId>..      <ar\n-00000e60: 7469 6661 6374 4964 3e6a 6176 6178 2e65  tifactId>javax.e\n-00000e70: 6c3c 2f61 7274 6966 6163 7449 643e 0d0a  l</artifactId>..\n-00000e80: 2020 2020 2020 3c73 636f 7065 3e74 6573        <scope>tes\n-00000e90: 743c 2f73 636f 7065 3e0d 0a20 2020 203c  t</scope>..    <\n-00000ea0: 2f64 6570 656e 6465 6e63 793e 0d0a 2020  /dependency>..  \n-00000eb0: 3c2f 6465 7065 6e64 656e 6369 6573 3e0d  </dependencies>.\n-00000ec0: 0a20 203c 6275 696c 643e 0d0a 2020 2020  .  <build>..    \n-00000ed0: 3c70 6c75 6769 6e73 3e0d 0a20 2020 2020  <plugins>..     \n-00000ee0: 203c 706c 7567 696e 3e0d 0a20 2020 2020   <plugin>..     \n-00000ef0: 2020 203c 6172 7469 6661 6374 4964 3e6d     <artifactId>m\n-00000f00: 6176 656e 2d73 7572 6566 6972 652d 706c  aven-surefire-pl\n-00000f10: 7567 696e 3c2f 6172 7469 6661 6374 4964  ugin</artifactId\n-00000f20: 3e0d 0a20 2020 2020 2020 203c 636f 6e66  >..        <conf\n-00000f30: 6967 7572 6174 696f 6e3e 0d0a 2020 2020  iguration>..    \n-00000f40: 2020 2020 2020 3c72 756e 4f72 6465 723e        <runOrder>\n-00000f50: 616c 7068 6162 6574 6963 616c 3c2f 7275  alphabetical</ru\n-00000f60: 6e4f 7264 6572 3e0d 0a20 2020 2020 2020  nOrder>..       \n-00000f70: 203c 2f63 6f6e 6669 6775 7261 7469 6f6e   </configuration\n-00000f80: 3e0d 0a20 2020 2020 203c 2f70 6c75 6769  >..      </plugi\n-00000f90: 6e3e 0d0a 2020 2020 3c2f 706c 7567 696e  n>..    </plugin\n-00000fa0: 733e 0d0a 2020 3c2f 6275 696c 643e 0d0a  s>..  </build>..\n-00000fb0: 3c2f 7072 6f6a 6563 743e 0d0a            </project>..\n+00000020: 462d 3822 3f3e 0a3c 212d 2d0a 2020 4c69  F-8\"?>.<!--.  Li\n+00000030: 6365 6e73 6564 2074 6f20 7468 6520 4170  censed to the Ap\n+00000040: 6163 6865 2053 6f66 7477 6172 6520 466f  ache Software Fo\n+00000050: 756e 6461 7469 6f6e 2028 4153 4629 2075  undation (ASF) u\n+00000060: 6e64 6572 206f 6e65 206f 7220 6d6f 7265  nder one or more\n+00000070: 0a20 2063 6f6e 7472 6962 7574 6f72 206c  .  contributor l\n+00000080: 6963 656e 7365 2061 6772 6565 6d65 6e74  icense agreement\n+00000090: 732e 2020 5365 6520 7468 6520 4e4f 5449  s.  See the NOTI\n+000000a0: 4345 2066 696c 6520 6469 7374 7269 6275  CE file distribu\n+000000b0: 7465 6420 7769 7468 0a20 2074 6869 7320  ted with.  this \n+000000c0: 776f 726b 2066 6f72 2061 6464 6974 696f  work for additio\n+000000d0: 6e61 6c20 696e 666f 726d 6174 696f 6e20  nal information \n+000000e0: 7265 6761 7264 696e 6720 636f 7079 7269  regarding copyri\n+000000f0: 6768 7420 6f77 6e65 7273 6869 702e 0a20  ght ownership.. \n+00000100: 2054 6865 2041 5346 206c 6963 656e 7365   The ASF license\n+00000110: 7320 7468 6973 2066 696c 6520 746f 2059  s this file to Y\n+00000120: 6f75 2075 6e64 6572 2074 6865 2041 7061  ou under the Apa\n+00000130: 6368 6520 4c69 6365 6e73 652c 2056 6572  che License, Ver\n+00000140: 7369 6f6e 2032 2e30 0a20 2028 7468 6520  sion 2.0.  (the \n+00000150: 224c 6963 656e 7365 2229 3b20 796f 7520  \"License\"); you \n+00000160: 6d61 7920 6e6f 7420 7573 6520 7468 6973  may not use this\n+00000170: 2066 696c 6520 6578 6365 7074 2069 6e20   file except in \n+00000180: 636f 6d70 6c69 616e 6365 2077 6974 680a  compliance with.\n+00000190: 2020 7468 6520 4c69 6365 6e73 652e 2020    the License.  \n+000001a0: 596f 7520 6d61 7920 6f62 7461 696e 2061  You may obtain a\n+000001b0: 2063 6f70 7920 6f66 2074 6865 204c 6963   copy of the Lic\n+000001c0: 656e 7365 2061 740a 0a20 2020 2020 2068  ense at..      h\n+000001d0: 7474 703a 2f2f 7777 772e 6170 6163 6865  ttp://www.apache\n+000001e0: 2e6f 7267 2f6c 6963 656e 7365 732f 4c49  .org/licenses/LI\n+000001f0: 4345 4e53 452d 322e 300a 0a20 2055 6e6c  CENSE-2.0..  Unl\n+00000200: 6573 7320 7265 7175 6972 6564 2062 7920  ess required by \n+00000210: 6170 706c 6963 6162 6c65 206c 6177 206f  applicable law o\n+00000220: 7220 6167 7265 6564 2074 6f20 696e 2077  r agreed to in w\n+00000230: 7269 7469 6e67 2c20 736f 6674 7761 7265  riting, software\n+00000240: 0a20 2064 6973 7472 6962 7574 6564 2075  .  distributed u\n+00000250: 6e64 6572 2074 6865 204c 6963 656e 7365  nder the License\n+00000260: 2069 7320 6469 7374 7269 6275 7465 6420   is distributed \n+00000270: 6f6e 2061 6e20 2241 5320 4953 2220 4241  on an \"AS IS\" BA\n+00000280: 5349 532c 0a20 2057 4954 484f 5554 2057  SIS,.  WITHOUT W\n+00000290: 4152 5241 4e54 4945 5320 4f52 2043 4f4e  ARRANTIES OR CON\n+000002a0: 4449 5449 4f4e 5320 4f46 2041 4e59 204b  DITIONS OF ANY K\n+000002b0: 494e 442c 2065 6974 6865 7220 6578 7072  IND, either expr\n+000002c0: 6573 7320 6f72 2069 6d70 6c69 6564 2e0a  ess or implied..\n+000002d0: 2020 5365 6520 7468 6520 4c69 6365 6e73    See the Licens\n+000002e0: 6520 666f 7220 7468 6520 7370 6563 6966  e for the specif\n+000002f0: 6963 206c 616e 6775 6167 6520 676f 7665  ic language gove\n+00000300: 726e 696e 6720 7065 726d 6973 7369 6f6e  rning permission\n+00000310: 7320 616e 640a 2020 6c69 6d69 7461 7469  s and.  limitati\n+00000320: 6f6e 7320 756e 6465 7220 7468 6520 4c69  ons under the Li\n+00000330: 6365 6e73 652e 0a20 202d 2d3e 0a3c 7072  cense..  -->.<pr\n+00000340: 6f6a 6563 7420 7873 693a 7363 6865 6d61  oject xsi:schema\n+00000350: 4c6f 6361 7469 6f6e 3d22 6874 7470 3a2f  Location=\"http:/\n+00000360: 2f6d 6176 656e 2e61 7061 6368 652e 6f72  /maven.apache.or\n+00000370: 672f 504f 4d2f 342e 302e 3020 6874 7470  g/POM/4.0.0 http\n+00000380: 733a 2f2f 6d61 7665 6e2e 6170 6163 6865  s://maven.apache\n+00000390: 2e6f 7267 2f78 7364 2f6d 6176 656e 2d34  .org/xsd/maven-4\n+000003a0: 2e30 2e30 2e78 7364 2220 786d 6c6e 733d  .0.0.xsd\" xmlns=\n+000003b0: 2268 7474 703a 2f2f 6d61 7665 6e2e 6170  \"http://maven.ap\n+000003c0: 6163 6865 2e6f 7267 2f50 4f4d 2f34 2e30  ache.org/POM/4.0\n+000003d0: 2e30 220a 2020 2020 786d 6c6e 733a 7873  .0\".    xmlns:xs\n+000003e0: 693d 2268 7474 703a 2f2f 7777 772e 7733  i=\"http://www.w3\n+000003f0: 2e6f 7267 2f32 3030 312f 584d 4c53 6368  .org/2001/XMLSch\n+00000400: 656d 612d 696e 7374 616e 6365 223e 0a20  ema-instance\">. \n+00000410: 203c 6d6f 6465 6c56 6572 7369 6f6e 3e34   <modelVersion>4\n+00000420: 2e30 2e30 3c2f 6d6f 6465 6c56 6572 7369  .0.0</modelVersi\n+00000430: 6f6e 3e0a 2020 3c70 6172 656e 743e 0a20  on>.  <parent>. \n+00000440: 2020 203c 6772 6f75 7049 643e 6f72 672e     <groupId>org.\n+00000450: 6170 6163 6865 2e64 7562 626f 3c2f 6772  apache.dubbo</gr\n+00000460: 6f75 7049 643e 0a20 2020 203c 6172 7469  oupId>.    <arti\n+00000470: 6661 6374 4964 3e64 7562 626f 2d72 7063  factId>dubbo-rpc\n+00000480: 3c2f 6172 7469 6661 6374 4964 3e0a 2020  </artifactId>.  \n+00000490: 2020 3c76 6572 7369 6f6e 3e32 2e37 2e31    <version>2.7.1\n+000004a0: 303c 2f76 6572 7369 6f6e 3e0a 2020 3c2f  0</version>.  </\n+000004b0: 7061 7265 6e74 3e0a 2020 3c67 726f 7570  parent>.  <group\n+000004c0: 4964 3e6f 7267 2e61 7061 6368 652e 6475  Id>org.apache.du\n+000004d0: 6262 6f3c 2f67 726f 7570 4964 3e0a 2020  bbo</groupId>.  \n+000004e0: 3c61 7274 6966 6163 7449 643e 6475 6262  <artifactId>dubb\n+000004f0: 6f2d 7270 632d 6475 6262 6f3c 2f61 7274  o-rpc-dubbo</art\n+00000500: 6966 6163 7449 643e 0a20 203c 7665 7273  ifactId>.  <vers\n+00000510: 696f 6e3e 322e 372e 3130 3c2f 7665 7273  ion>2.7.10</vers\n+00000520: 696f 6e3e 0a20 203c 6e61 6d65 3e24 7b70  ion>.  <name>${p\n+00000530: 726f 6a65 6374 2e61 7274 6966 6163 7449  roject.artifactI\n+00000540: 647d 3c2f 6e61 6d65 3e0a 2020 3c64 6573  d}</name>.  <des\n+00000550: 6372 6970 7469 6f6e 3e54 6865 2064 6566  cription>The def\n+00000560: 6175 6c74 2072 7063 206d 6f64 756c 6520  ault rpc module \n+00000570: 6f66 2064 7562 626f 2070 726f 6a65 6374  of dubbo project\n+00000580: 3c2f 6465 7363 7269 7074 696f 6e3e 0a20  </description>. \n+00000590: 203c 6c69 6365 6e73 6573 3e0a 2020 2020   <licenses>.    \n+000005a0: 3c6c 6963 656e 7365 3e0a 2020 2020 2020  <license>.      \n+000005b0: 3c6e 616d 653e 4170 6163 6865 204c 6963  <name>Apache Lic\n+000005c0: 656e 7365 2c20 5665 7273 696f 6e20 322e  ense, Version 2.\n+000005d0: 303c 2f6e 616d 653e 0a20 2020 2020 203c  0</name>.      <\n+000005e0: 7572 6c3e 6874 7470 3a2f 2f77 7777 2e61  url>http://www.a\n+000005f0: 7061 6368 652e 6f72 672f 6c69 6365 6e73  pache.org/licens\n+00000600: 6573 2f4c 4943 454e 5345 2d32 2e30 3c2f  es/LICENSE-2.0</\n+00000610: 7572 6c3e 0a20 2020 2020 203c 6469 7374  url>.      <dist\n+00000620: 7269 6275 7469 6f6e 3e72 6570 6f3c 2f64  ribution>repo</d\n+00000630: 6973 7472 6962 7574 696f 6e3e 0a20 2020  istribution>.   \n+00000640: 203c 2f6c 6963 656e 7365 3e0a 2020 3c2f   </license>.  </\n+00000650: 6c69 6365 6e73 6573 3e0a 2020 3c70 726f  licenses>.  <pro\n+00000660: 7065 7274 6965 733e 0a20 2020 203c 736b  perties>.    <sk\n+00000670: 6970 5f6d 6176 656e 5f64 6570 6c6f 793e  ip_maven_deploy>\n+00000680: 6661 6c73 653c 2f73 6b69 705f 6d61 7665  false</skip_mave\n+00000690: 6e5f 6465 706c 6f79 3e0a 2020 3c2f 7072  n_deploy>.  </pr\n+000006a0: 6f70 6572 7469 6573 3e0a 2020 3c64 6570  operties>.  <dep\n+000006b0: 656e 6465 6e63 6965 733e 0a20 2020 203c  endencies>.    <\n+000006c0: 6465 7065 6e64 656e 6379 3e0a 2020 2020  dependency>.    \n+000006d0: 2020 3c67 726f 7570 4964 3e6f 7267 2e61    <groupId>org.a\n+000006e0: 7061 6368 652e 6475 6262 6f3c 2f67 726f  pache.dubbo</gro\n+000006f0: 7570 4964 3e0a 2020 2020 2020 3c61 7274  upId>.      <art\n+00000700: 6966 6163 7449 643e 6475 6262 6f2d 7270  ifactId>dubbo-rp\n+00000710: 632d 6170 693c 2f61 7274 6966 6163 7449  c-api</artifactI\n+00000720: 643e 0a20 2020 2020 203c 7665 7273 696f  d>.      <versio\n+00000730: 6e3e 247b 7072 6f6a 6563 742e 7061 7265  n>${project.pare\n+00000740: 6e74 2e76 6572 7369 6f6e 7d3c 2f76 6572  nt.version}</ver\n+00000750: 7369 6f6e 3e0a 2020 2020 3c2f 6465 7065  sion>.    </depe\n+00000760: 6e64 656e 6379 3e0a 2020 2020 3c64 6570  ndency>.    <dep\n+00000770: 656e 6465 6e63 793e 0a20 2020 2020 203c  endency>.      <\n+00000780: 6772 6f75 7049 643e 6f72 672e 6170 6163  groupId>org.apac\n+00000790: 6865 2e64 7562 626f 3c2f 6772 6f75 7049  he.dubbo</groupI\n+000007a0: 643e 0a20 2020 2020 203c 6172 7469 6661  d>.      <artifa\n+000007b0: 6374 4964 3e64 7562 626f 2d72 656d 6f74  ctId>dubbo-remot\n+000007c0: 696e 672d 6170 693c 2f61 7274 6966 6163  ing-api</artifac\n+000007d0: 7449 643e 0a20 2020 2020 203c 7665 7273  tId>.      <vers\n+000007e0: 696f 6e3e 247b 7072 6f6a 6563 742e 7061  ion>${project.pa\n+000007f0: 7265 6e74 2e76 6572 7369 6f6e 7d3c 2f76  rent.version}</v\n+00000800: 6572 7369 6f6e 3e0a 2020 2020 3c2f 6465  ersion>.    </de\n+00000810: 7065 6e64 656e 6379 3e0a 2020 2020 3c64  pendency>.    <d\n+00000820: 6570 656e 6465 6e63 793e 0a20 2020 2020  ependency>.     \n+00000830: 203c 6772 6f75 7049 643e 6f72 672e 6170   <groupId>org.ap\n+00000840: 6163 6865 2e64 7562 626f 3c2f 6772 6f75  ache.dubbo</grou\n+00000850: 7049 643e 0a20 2020 2020 203c 6172 7469  pId>.      <arti\n+00000860: 6661 6374 4964 3e64 7562 626f 2d63 6c75  factId>dubbo-clu\n+00000870: 7374 6572 3c2f 6172 7469 6661 6374 4964  ster</artifactId\n+00000880: 3e0a 2020 2020 2020 3c76 6572 7369 6f6e  >.      <version\n+00000890: 3e24 7b70 726f 6a65 6374 2e70 6172 656e  >${project.paren\n+000008a0: 742e 7665 7273 696f 6e7d 3c2f 7665 7273  t.version}</vers\n+000008b0: 696f 6e3e 0a20 2020 203c 2f64 6570 656e  ion>.    </depen\n+000008c0: 6465 6e63 793e 0a20 2020 203c 6465 7065  dency>.    <depe\n+000008d0: 6e64 656e 6379 3e0a 2020 2020 2020 3c67  ndency>.      <g\n+000008e0: 726f 7570 4964 3e6f 7267 2e61 7061 6368  roupId>org.apach\n+000008f0: 652e 6475 6262 6f3c 2f67 726f 7570 4964  e.dubbo</groupId\n+00000900: 3e0a 2020 2020 2020 3c61 7274 6966 6163  >.      <artifac\n+00000910: 7449 643e 6475 6262 6f2d 7265 6d6f 7469  tId>dubbo-remoti\n+00000920: 6e67 2d6e 6574 7479 343c 2f61 7274 6966  ng-netty4</artif\n+00000930: 6163 7449 643e 0a20 2020 2020 203c 7665  actId>.      <ve\n+00000940: 7273 696f 6e3e 247b 7072 6f6a 6563 742e  rsion>${project.\n+00000950: 7061 7265 6e74 2e76 6572 7369 6f6e 7d3c  parent.version}<\n+00000960: 2f76 6572 7369 6f6e 3e0a 2020 2020 2020  /version>.      \n+00000970: 3c73 636f 7065 3e74 6573 743c 2f73 636f  <scope>test</sco\n+00000980: 7065 3e0a 2020 2020 3c2f 6465 7065 6e64  pe>.    </depend\n+00000990: 656e 6379 3e0a 2020 2020 3c64 6570 656e  ency>.    <depen\n+000009a0: 6465 6e63 793e 0a20 2020 2020 203c 6772  dency>.      <gr\n+000009b0: 6f75 7049 643e 6f72 672e 6170 6163 6865  oupId>org.apache\n+000009c0: 2e64 7562 626f 3c2f 6772 6f75 7049 643e  .dubbo</groupId>\n+000009d0: 0a20 2020 2020 203c 6172 7469 6661 6374  .      <artifact\n+000009e0: 4964 3e64 7562 626f 2d72 656d 6f74 696e  Id>dubbo-remotin\n+000009f0: 672d 6d69 6e61 3c2f 6172 7469 6661 6374  g-mina</artifact\n+00000a00: 4964 3e0a 2020 2020 2020 3c76 6572 7369  Id>.      <versi\n+00000a10: 6f6e 3e24 7b70 726f 6a65 6374 2e70 6172  on>${project.par\n+00000a20: 656e 742e 7665 7273 696f 6e7d 3c2f 7665  ent.version}</ve\n+00000a30: 7273 696f 6e3e 0a20 2020 2020 203c 7363  rsion>.      <sc\n+00000a40: 6f70 653e 7465 7374 3c2f 7363 6f70 653e  ope>test</scope>\n+00000a50: 0a20 2020 203c 2f64 6570 656e 6465 6e63  .    </dependenc\n+00000a60: 793e 0a20 2020 203c 6465 7065 6e64 656e  y>.    <dependen\n+00000a70: 6379 3e0a 2020 2020 2020 3c67 726f 7570  cy>.      <group\n+00000a80: 4964 3e69 6f2e 6e65 7474 793c 2f67 726f  Id>io.netty</gro\n+00000a90: 7570 4964 3e0a 2020 2020 2020 3c61 7274  upId>.      <art\n+00000aa0: 6966 6163 7449 643e 6e65 7474 792d 616c  ifactId>netty-al\n+00000ab0: 6c3c 2f61 7274 6966 6163 7449 643e 0a20  l</artifactId>. \n+00000ac0: 2020 2020 203c 7363 6f70 653e 7465 7374       <scope>test\n+00000ad0: 3c2f 7363 6f70 653e 0a20 2020 203c 2f64  </scope>.    </d\n+00000ae0: 6570 656e 6465 6e63 793e 0a20 2020 203c  ependency>.    <\n+00000af0: 6465 7065 6e64 656e 6379 3e0a 2020 2020  dependency>.    \n+00000b00: 2020 3c67 726f 7570 4964 3e6f 7267 2e61    <groupId>org.a\n+00000b10: 7061 6368 652e 6475 6262 6f3c 2f67 726f  pache.dubbo</gro\n+00000b20: 7570 4964 3e0a 2020 2020 2020 3c61 7274  upId>.      <art\n+00000b30: 6966 6163 7449 643e 6475 6262 6f2d 7365  ifactId>dubbo-se\n+00000b40: 7269 616c 697a 6174 696f 6e2d 6865 7373  rialization-hess\n+00000b50: 6961 6e32 3c2f 6172 7469 6661 6374 4964  ian2</artifactId\n+00000b60: 3e0a 2020 2020 2020 3c76 6572 7369 6f6e  >.      <version\n+00000b70: 3e24 7b70 726f 6a65 6374 2e70 6172 656e  >${project.paren\n+00000b80: 742e 7665 7273 696f 6e7d 3c2f 7665 7273  t.version}</vers\n+00000b90: 696f 6e3e 0a20 2020 2020 203c 7363 6f70  ion>.      <scop\n+00000ba0: 653e 7465 7374 3c2f 7363 6f70 653e 0a20  e>test</scope>. \n+00000bb0: 2020 203c 2f64 6570 656e 6465 6e63 793e     </dependency>\n+00000bc0: 0a20 2020 203c 6465 7065 6e64 656e 6379  .    <dependency\n+00000bd0: 3e0a 2020 2020 2020 3c67 726f 7570 4964  >.      <groupId\n+00000be0: 3e6f 7267 2e61 7061 6368 652e 6475 6262  >org.apache.dubb\n+00000bf0: 6f3c 2f67 726f 7570 4964 3e0a 2020 2020  o</groupId>.    \n+00000c00: 2020 3c61 7274 6966 6163 7449 643e 6475    <artifactId>du\n+00000c10: 6262 6f2d 7365 7269 616c 697a 6174 696f  bbo-serializatio\n+00000c20: 6e2d 6a64 6b3c 2f61 7274 6966 6163 7449  n-jdk</artifactI\n+00000c30: 643e 0a20 2020 2020 203c 7665 7273 696f  d>.      <versio\n+00000c40: 6e3e 247b 7072 6f6a 6563 742e 7061 7265  n>${project.pare\n+00000c50: 6e74 2e76 6572 7369 6f6e 7d3c 2f76 6572  nt.version}</ver\n+00000c60: 7369 6f6e 3e0a 2020 2020 2020 3c73 636f  sion>.      <sco\n+00000c70: 7065 3e74 6573 743c 2f73 636f 7065 3e0a  pe>test</scope>.\n+00000c80: 2020 2020 3c2f 6465 7065 6e64 656e 6379      </dependency\n+00000c90: 3e0a 2020 2020 3c64 6570 656e 6465 6e63  >.    <dependenc\n+00000ca0: 793e 0a20 2020 2020 203c 6772 6f75 7049  y>.      <groupI\n+00000cb0: 643e 6a61 7661 782e 7661 6c69 6461 7469  d>javax.validati\n+00000cc0: 6f6e 3c2f 6772 6f75 7049 643e 0a20 2020  on</groupId>.   \n+00000cd0: 2020 203c 6172 7469 6661 6374 4964 3e76     <artifactId>v\n+00000ce0: 616c 6964 6174 696f 6e2d 6170 693c 2f61  alidation-api</a\n+00000cf0: 7274 6966 6163 7449 643e 0a20 2020 2020  rtifactId>.     \n+00000d00: 203c 7363 6f70 653e 7465 7374 3c2f 7363   <scope>test</sc\n+00000d10: 6f70 653e 0a20 2020 203c 2f64 6570 656e  ope>.    </depen\n+00000d20: 6465 6e63 793e 0a20 2020 203c 6465 7065  dency>.    <depe\n+00000d30: 6e64 656e 6379 3e0a 2020 2020 2020 3c67  ndency>.      <g\n+00000d40: 726f 7570 4964 3e6f 7267 2e68 6962 6572  roupId>org.hiber\n+00000d50: 6e61 7465 3c2f 6772 6f75 7049 643e 0a20  nate</groupId>. \n+00000d60: 2020 2020 203c 6172 7469 6661 6374 4964       <artifactId\n+00000d70: 3e68 6962 6572 6e61 7465 2d76 616c 6964  >hibernate-valid\n+00000d80: 6174 6f72 3c2f 6172 7469 6661 6374 4964  ator</artifactId\n+00000d90: 3e0a 2020 2020 2020 3c73 636f 7065 3e74  >.      <scope>t\n+00000da0: 6573 743c 2f73 636f 7065 3e0a 2020 2020  est</scope>.    \n+00000db0: 3c2f 6465 7065 6e64 656e 6379 3e0a 2020  </dependency>.  \n+00000dc0: 2020 3c64 6570 656e 6465 6e63 793e 0a20    <dependency>. \n+00000dd0: 2020 2020 203c 6772 6f75 7049 643e 6f72       <groupId>or\n+00000de0: 672e 676c 6173 7366 6973 683c 2f67 726f  g.glassfish</gro\n+00000df0: 7570 4964 3e0a 2020 2020 2020 3c61 7274  upId>.      <art\n+00000e00: 6966 6163 7449 643e 6a61 7661 782e 656c  ifactId>javax.el\n+00000e10: 3c2f 6172 7469 6661 6374 4964 3e0a 2020  </artifactId>.  \n+00000e20: 2020 2020 3c73 636f 7065 3e74 6573 743c      <scope>test<\n+00000e30: 2f73 636f 7065 3e0a 2020 2020 3c2f 6465  /scope>.    </de\n+00000e40: 7065 6e64 656e 6379 3e0a 2020 3c2f 6465  pendency>.  </de\n+00000e50: 7065 6e64 656e 6369 6573 3e0a 2020 3c62  pendencies>.  <b\n+00000e60: 7569 6c64 3e0a 2020 2020 3c70 6c75 6769  uild>.    <plugi\n+00000e70: 6e73 3e0a 2020 2020 2020 3c70 6c75 6769  ns>.      <plugi\n+00000e80: 6e3e 0a20 2020 2020 2020 203c 6172 7469  n>.        <arti\n+00000e90: 6661 6374 4964 3e6d 6176 656e 2d73 7572  factId>maven-sur\n+00000ea0: 6566 6972 652d 706c 7567 696e 3c2f 6172  efire-plugin</ar\n+00000eb0: 7469 6661 6374 4964 3e0a 2020 2020 2020  tifactId>.      \n+00000ec0: 2020 3c63 6f6e 6669 6775 7261 7469 6f6e    <configuration\n+00000ed0: 3e0a 2020 2020 2020 2020 2020 3c72 756e  >.          <run\n+00000ee0: 4f72 6465 723e 616c 7068 6162 6574 6963  Order>alphabetic\n+00000ef0: 616c 3c2f 7275 6e4f 7264 6572 3e0a 2020  al</runOrder>.  \n+00000f00: 2020 2020 2020 3c2f 636f 6e66 6967 7572        </configur\n+00000f10: 6174 696f 6e3e 0a20 2020 2020 203c 2f70  ation>.      </p\n+00000f20: 6c75 6769 6e3e 0a20 2020 203c 2f70 6c75  lugin>.    </plu\n+00000f30: 6769 6e73 3e0a 2020 3c2f 6275 696c 643e  gins>.  </build>\n+00000f40: 0a3c 2f70 726f 6a65 6374 3e0a            .</project>.\n"}]}
