Compare commits
474 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a78c2145e6 | ||
|
|
ee20a34a70 | ||
|
|
33bd80c572 | ||
|
|
031309b105 | ||
|
|
bcbd981a9b | ||
|
|
b7ce390c33 | ||
|
|
c9d099c694 | ||
|
|
fcca0329c6 | ||
|
|
c82c0bc680 | ||
|
|
2921478a0a | ||
|
|
61a5420d48 | ||
|
|
702ab6ef6e | ||
|
|
2576e71a7d | ||
|
|
0d0bd78213 | ||
|
|
8d9fa8f9cf | ||
|
|
25eaf6e353 | ||
|
|
8afcaa0b34 | ||
|
|
1824f8150c | ||
|
|
2f89778fd6 | ||
|
|
f9d250b43c | ||
|
|
3a3c09d8aa | ||
|
|
09a0d4f9e2 | ||
|
|
3bba781183 | ||
|
|
6426f8fe91 | ||
|
|
5906594148 | ||
|
|
1b188c863c | ||
|
|
087b4cb571 | ||
|
|
c9496b6231 | ||
|
|
60d95d7628 | ||
|
|
dd9e7e77b5 | ||
|
|
50c9363876 | ||
|
|
938e357745 | ||
|
|
08ee51f8ab | ||
|
|
40ae555645 | ||
|
|
33f89264a6 | ||
|
|
e4ea20cc5f | ||
|
|
045b7db1af | ||
|
|
676c1b5d21 | ||
|
|
e4319246b8 | ||
|
|
32d8515bf4 | ||
|
|
d7e7113201 | ||
|
|
9493aa43a7 | ||
|
|
d07c55b831 | ||
|
|
47dab88d72 | ||
|
|
9e553aeff6 | ||
|
|
ed8e754557 | ||
|
|
651dc3df2a | ||
|
|
84e5bc3437 | ||
|
|
64fd0176ac | ||
|
|
c1f3115d4e | ||
|
|
1c70834760 | ||
|
|
7c901731bc | ||
|
|
2b2d53e515 | ||
|
|
be051ecf45 | ||
|
|
18534eb654 | ||
|
|
a5a926fd94 | ||
|
|
0cb9f2cad3 | ||
|
|
98209cc82e | ||
|
|
1879afa6a4 | ||
|
|
4a6404dfec | ||
|
|
0fa1c4a08f | ||
|
|
573d7c5776 | ||
|
|
c56c9bf260 | ||
|
|
387865789f | ||
|
|
03fcf43a89 | ||
|
|
df8090813a | ||
|
|
849b29d00f | ||
|
|
4b7f65e1c4 | ||
|
|
4545d81e50 | ||
|
|
1ac5f060a4 | ||
|
|
7e1ff8e315 | ||
|
|
4e0c1fee97 | ||
|
|
0b38f23f2d | ||
|
|
98ea6861c1 | ||
|
|
c07b628ea1 | ||
|
|
b1b979c0b5 | ||
|
|
35b708b01d | ||
|
|
229ae0d44f | ||
|
|
7d6897fa36 | ||
|
|
5851093590 | ||
|
|
4646c1d1f0 | ||
|
|
f3763dbf72 | ||
|
|
6a8c60ec78 | ||
|
|
ae437fd5d6 | ||
|
|
7251c984c8 | ||
|
|
ec449220eb | ||
|
|
78265944f0 | ||
|
|
d2791f6d1b | ||
|
|
d525d2664b | ||
|
|
a4ccea91ad | ||
|
|
750da161eb | ||
|
|
ac50312f0b | ||
|
|
8d44d48072 | ||
|
|
6c2baa1708 | ||
|
|
4525cfe594 | ||
|
|
921f96c975 | ||
|
|
29ce57d3af | ||
|
|
2ca1e6305c | ||
|
|
827b404a57 | ||
|
|
83569142c1 | ||
|
|
2da0faacc3 | ||
|
|
cf51bee2cc | ||
|
|
0dd55dc947 | ||
|
|
620fa0430c | ||
|
|
d053590257 | ||
|
|
684af3de61 | ||
|
|
6c6e26ed0b | ||
|
|
4a05bfbd08 | ||
|
|
787dc7b32f | ||
|
|
85a1f99f6e | ||
|
|
4fe8a1199e | ||
|
|
7312dbc4c5 | ||
|
|
cfecfabc92 | ||
|
|
587160c5fe | ||
|
|
ee7fe3ed33 | ||
|
|
47d4a6cc29 | ||
|
|
c1e4763369 | ||
|
|
333ba0f162 | ||
|
|
e039b0e9f6 | ||
|
|
b3c5e3beca | ||
|
|
70ba45c3bd | ||
|
|
14ae44fcac | ||
|
|
f7618f5da4 | ||
|
|
d6c6e4c02e | ||
|
|
9365052b85 | ||
|
|
ef88063094 | ||
|
|
4cbaf85eea | ||
|
|
6c07123da3 | ||
|
|
04a4ce12c7 | ||
|
|
e00ed8ae37 | ||
|
|
218a79b60a | ||
|
|
19ae86c71f | ||
|
|
9250d4e64d | ||
|
|
9f5aa58a31 | ||
|
|
c8b0a88573 | ||
|
|
7cf3f49aa1 | ||
|
|
be2c803f82 | ||
|
|
fd1197e8dc | ||
|
|
115f91b64a | ||
|
|
dfb800473a | ||
|
|
c69c1bb134 | ||
|
|
5b501c7c2f | ||
|
|
8d5ce56ec2 | ||
|
|
15c97ddc18 | ||
|
|
36d7fbf4e9 | ||
|
|
919e7aa5c6 | ||
|
|
2174de2b71 | ||
|
|
cb9e914e44 | ||
|
|
15f856b762 | ||
|
|
991dba0d62 | ||
|
|
aa2685d6e4 | ||
|
|
0952150328 | ||
|
|
e6ef4d1546 | ||
|
|
16cf85abb9 | ||
|
|
5afe0ead94 | ||
|
|
b6c933f989 | ||
|
|
feaf1a1f06 | ||
|
|
6b54c6e886 | ||
|
|
a95b69ab79 | ||
|
|
a2492ae248 | ||
|
|
0db1c4413c | ||
|
|
8718bca6e8 | ||
|
|
6486863d00 | ||
|
|
bfc2397dbf | ||
|
|
0cfdb9795b | ||
|
|
d327757d59 | ||
|
|
e88c4fa2e3 | ||
|
|
69a0071e17 | ||
|
|
d3cfe809e7 | ||
|
|
0ca6e5401a | ||
|
|
8ff2b60ed4 | ||
|
|
1dbe125e27 | ||
|
|
32a595262d | ||
|
|
01431a93a4 | ||
|
|
00a12d8113 | ||
|
|
0f2474386c | ||
|
|
5de52ed6e8 | ||
|
|
099b3fb7f3 | ||
|
|
ed85e33403 | ||
|
|
daff7d095f | ||
|
|
a8ff82229f | ||
|
|
2874e7d195 | ||
|
|
8baea2657d | ||
|
|
03e9a5cbcb | ||
|
|
8d2f2a28af | ||
|
|
4a4bade180 | ||
|
|
28e72f9883 | ||
|
|
681e3967d2 | ||
|
|
640dcbc8d7 | ||
|
|
19276ecb91 | ||
|
|
9f9078cdc5 | ||
|
|
9bd1e0c97b | ||
|
|
c2c8f700a2 | ||
|
|
86895eb5ef | ||
|
|
e8dacd6b70 | ||
|
|
03fcf1dc95 | ||
|
|
953b2be224 | ||
|
|
55645ba2a0 | ||
|
|
858c6a0aaf | ||
|
|
85d4023fa2 | ||
|
|
607fc8e45f | ||
|
|
511a966ce5 | ||
|
|
6d135efbc6 | ||
|
|
5dff6310aa | ||
|
|
194a06c748 | ||
|
|
1ce97aa20d | ||
|
|
1c88fb0355 | ||
|
|
7b81c42377 | ||
|
|
1afa38a947 | ||
|
|
eedb418299 | ||
|
|
9efc14e627 | ||
|
|
0dc3d65307 | ||
|
|
e3ddbe609c | ||
|
|
f115934499 | ||
|
|
f5e290a47a | ||
|
|
29cd395888 | ||
|
|
9ca7855756 | ||
|
|
1f1ab112eb | ||
|
|
b172b66263 | ||
|
|
b08f9f5757 | ||
|
|
32e65ff304 | ||
|
|
40126c923e | ||
|
|
83ae5b0a13 | ||
|
|
aea6a2839d | ||
|
|
6211d9ff18 | ||
|
|
0e7fab71b8 | ||
|
|
a106c8ed60 | ||
|
|
ae52d0ab3d | ||
|
|
c993cd5b5a | ||
|
|
9bdd83cc6e | ||
|
|
1b6a23c1a9 | ||
|
|
2703d94b83 | ||
|
|
4cb51ecbe6 | ||
|
|
0cf64121ae | ||
|
|
58eb3c5d64 | ||
|
|
3c645b4c7f | ||
|
|
a540eed0ed | ||
|
|
ad567b4c40 | ||
|
|
6f8aeea870 | ||
|
|
87a1a7c641 | ||
|
|
178f96a3b5 | ||
|
|
cc629a1a7c | ||
|
|
1cb72df52e | ||
|
|
4c32422493 | ||
|
|
7361823ece | ||
|
|
03824a900c | ||
|
|
c40913d690 | ||
|
|
bdfdf153f7 | ||
|
|
fa9e62d2a7 | ||
|
|
bcca20dbbb | ||
|
|
bca42ee7b4 | ||
|
|
d5f2bae47c | ||
|
|
fe1e99c67c | ||
|
|
699d55d70e | ||
|
|
3d11a95a29 | ||
|
|
a983c53189 | ||
|
|
0ee28f59ce | ||
|
|
96ee0584b8 | ||
|
|
7352d5b8ed | ||
|
|
e79fdd887c | ||
|
|
7b5b0f34ff | ||
|
|
ae8fb992fb | ||
|
|
d5409518ed | ||
|
|
6bb2e152a5 | ||
|
|
c73ebf88db | ||
|
|
bfdceec81b | ||
|
|
dd444e3a0f | ||
|
|
79de8dbbca | ||
|
|
5c6f3c3712 | ||
|
|
0d0663a7de | ||
|
|
6d1c4e6c85 | ||
|
|
f539633497 | ||
|
|
d9ddd6d772 | ||
|
|
4a2ba4e914 | ||
|
|
cc864e3e69 | ||
|
|
4cd5bd37d3 | ||
|
|
ff14e675fa | ||
|
|
a46cb462a2 | ||
|
|
8077dedd03 | ||
|
|
6a707dff0c | ||
|
|
c9aa31d803 | ||
|
|
4494683db2 | ||
|
|
f440b2d639 | ||
|
|
324d4bd94e | ||
|
|
bb82d70f5a | ||
|
|
8d1022f70f | ||
|
|
00034981ef | ||
|
|
2b3b33979c | ||
|
|
8e0788ccf3 | ||
|
|
6e81541a3b | ||
|
|
6acb17da7c | ||
|
|
774286952b | ||
|
|
35a3c81391 | ||
|
|
90d28eb4f4 | ||
|
|
aab24fdbbe | ||
|
|
d0c24ed7a7 | ||
|
|
2260906396 | ||
|
|
0901195147 | ||
|
|
c11a8e7bd9 | ||
|
|
8176ec1b0a | ||
|
|
8f598fe4eb | ||
|
|
2fac5c853e | ||
|
|
4dbd6b57f8 | ||
|
|
a5f21a99d8 | ||
|
|
6f98b44471 | ||
|
|
b13b07fb05 | ||
|
|
1f8884a415 | ||
|
|
848a30b2db | ||
|
|
350ece1533 | ||
|
|
513183f55c | ||
|
|
b23434e3bb | ||
|
|
7084fb2ea2 | ||
|
|
5becdf4d50 | ||
|
|
5aa10e9d74 | ||
|
|
db462ec134 | ||
|
|
75e9f6162b | ||
|
|
970d530fbd | ||
|
|
13ffa2a3e5 | ||
|
|
8416826827 | ||
|
|
0a296ee857 | ||
|
|
bb45470078 | ||
|
|
d3c6ab8dc5 | ||
|
|
0bf34781c5 | ||
|
|
20940e82de | ||
|
|
78df572bec | ||
|
|
ffd0bec5c6 | ||
|
|
62783d0765 | ||
|
|
7116f33a3a | ||
|
|
a168dab8c0 | ||
|
|
e3e065f36e | ||
|
|
d282321d98 | ||
|
|
1abdb3b874 | ||
|
|
1807287321 | ||
|
|
a29652180b | ||
|
|
d4a85ac136 | ||
|
|
007f635081 | ||
|
|
f75e15a375 | ||
|
|
508c7c4c0a | ||
|
|
7166dc0ec0 | ||
|
|
1f28b7e803 | ||
|
|
5d77139965 | ||
|
|
126dab08b2 | ||
|
|
a8175d9e19 | ||
|
|
a5c11b5119 | ||
|
|
bfc6b04a30 | ||
|
|
a5dd878c66 | ||
|
|
ed7ce80565 | ||
|
|
e6b71a3975 | ||
|
|
ff5049edc9 | ||
|
|
a34218367b | ||
|
|
f712107fb8 | ||
|
|
fb3dd6049d | ||
|
|
13bd467152 | ||
|
|
d934f615ca | ||
|
|
5e5280a7fd | ||
|
|
be2a4d252f | ||
|
|
0392fd68a8 | ||
|
|
e642854e99 | ||
|
|
1a42292725 | ||
|
|
c523a761c5 | ||
|
|
a416ae564a | ||
|
|
ecd647ecc4 | ||
|
|
50d0096492 | ||
|
|
1a2d43479f | ||
|
|
2416e93004 | ||
|
|
db99445878 | ||
|
|
18459b71c2 | ||
|
|
16cbabc79d | ||
|
|
c470d31605 | ||
|
|
cdacc30633 | ||
|
|
e55d4d8a78 | ||
|
|
fcd3258a73 | ||
|
|
a8e9822381 | ||
|
|
dfdb37973f | ||
|
|
3f340a3f7e | ||
|
|
e64d522707 | ||
|
|
6c05a4a038 | ||
|
|
5c9279cca4 | ||
|
|
a4ae6dd9c4 | ||
|
|
ace4042649 | ||
|
|
76debd5c82 | ||
|
|
8c0db6db53 | ||
|
|
bc99f3f295 | ||
|
|
826aaf0128 | ||
|
|
754861e036 | ||
|
|
b1bbc50472 | ||
|
|
dcb6c6d3f8 | ||
|
|
3f608b91e9 | ||
|
|
9d488974a4 | ||
|
|
1fa834f559 | ||
|
|
812f83446e | ||
|
|
3497ab0c73 | ||
|
|
78de131f83 | ||
|
|
3a8ffa11fe | ||
|
|
dd62d82005 | ||
|
|
7b9c71dcda | ||
|
|
4a518f1309 | ||
|
|
3a0a717765 | ||
|
|
60bdf4d137 | ||
|
|
0ec329927a | ||
|
|
6a616b4652 | ||
|
|
0bf7ccd701 | ||
|
|
c924d936f3 | ||
|
|
ef1c437191 | ||
|
|
6e6d0529d6 | ||
|
|
2ab179568f | ||
|
|
dab56caa98 | ||
|
|
67afd13fbb | ||
|
|
3a26ddd539 | ||
|
|
5197d63c70 | ||
|
|
3d136b843e | ||
|
|
388b7fbba7 | ||
|
|
a833f20729 | ||
|
|
d3c63bf35a | ||
|
|
5a0eff2b67 | ||
|
|
e64a75cfab | ||
|
|
2d31b8521d | ||
|
|
60225e3f5f | ||
|
|
aeb7b38474 | ||
|
|
bfbcab4009 | ||
|
|
742c352080 | ||
|
|
643827354c | ||
|
|
2f7bebfc17 | ||
|
|
7bf8d60ddf | ||
|
|
09c51b6b4e | ||
|
|
84f6ce58a0 | ||
|
|
9e90ae5285 | ||
|
|
93b1c9f0d9 | ||
|
|
dab8ed8ceb | ||
|
|
f016e49111 | ||
|
|
b403f22284 | ||
|
|
ccb9ac93f7 | ||
|
|
72935f1ebe | ||
|
|
1f7d46219a | ||
|
|
9094f76de2 | ||
|
|
d67cbeb3f2 | ||
|
|
90562ebd04 | ||
|
|
b14e14659c | ||
|
|
84a15afc9a | ||
|
|
8c1aba5608 | ||
|
|
a72c689f07 | ||
|
|
1d74f34575 | ||
|
|
a24092d391 | ||
|
|
097ae701c1 | ||
|
|
e250a593a7 | ||
|
|
1547e6b714 | ||
|
|
9f14224269 | ||
|
|
ecc54f9bd5 | ||
|
|
521ee56d31 | ||
|
|
f9da063532 | ||
|
|
5070c27f6a | ||
|
|
c0664bb0a9 | ||
|
|
f8c92f1ec4 | ||
|
|
01930cfdc8 | ||
|
|
e76e321765 | ||
|
|
99d2db31f7 | ||
|
|
fa9015447b | ||
|
|
735ad0908b | ||
|
|
a080a6a8cc | ||
|
|
2cbc51cfdf | ||
|
|
8631b4bdf5 | ||
|
|
285cb86891 | ||
|
|
bf535a7161 | ||
|
|
34e37471b8 | ||
|
|
e223548b23 | ||
|
|
3a13d242f6 | ||
|
|
204e6ec99f | ||
|
|
7e348782e4 | ||
|
|
a4cbe7db17 | ||
|
|
f8101acb4b | ||
|
|
9ed2d59317 | ||
|
|
0329ad7832 | ||
|
|
53df45456f | ||
|
|
93698bacff |
@@ -4,4 +4,4 @@ SET APP_HOME=%~dp0
|
|||||||
|
|
||||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||||
|
|
||||||
java -DCMD=APIDOC -DAPP_HOME=%APP_HOME% -classpath %APP_HOME%\lib\* org.redkale.boot.Application
|
java -DCMD=APIDOC -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ SET APP_HOME=%~dp0
|
|||||||
|
|
||||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||||
|
|
||||||
call %APP_HOME%\bin\shutdown.bat
|
call "%APP_HOME%\bin\shutdown.bat"
|
||||||
|
|
||||||
call %APP_HOME%\bin\start.bat
|
call "%APP_HOME%\bin\start.bat"
|
||||||
@@ -14,7 +14,7 @@ fi
|
|||||||
|
|
||||||
cd "$APP_HOME"
|
cd "$APP_HOME"
|
||||||
|
|
||||||
./bin/shutdown.sh
|
"$APP_HOME"/bin/shutdown.sh
|
||||||
|
|
||||||
./bin/start.sh
|
"$APP_HOME"/bin/start.sh
|
||||||
|
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ SET APP_HOME=%~dp0
|
|||||||
|
|
||||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||||
|
|
||||||
java -DCMD=SHUTDOWN -DAPP_HOME=%APP_HOME% -classpath %APP_HOME%\lib\* org.redkale.boot.Application
|
java -DCMD=SHUTDOWN -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
|
|
||||||
SET APP_HOME=%~dp0
|
SET APP_HOME=%~dp0
|
||||||
|
|
||||||
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
IF NOT EXIST "%APP_HOME%\conf\application.xml" SET APP_HOME=%~dp0..
|
||||||
|
|
||||||
java -DAPP_HOME=%APP_HOME% -classpath %APP_HOME%\lib\* org.redkale.boot.Application
|
java -DAPP_HOME="%APP_HOME%" -classpath "%APP_HOME%"\lib\* org.redkale.boot.Application
|
||||||
|
|
||||||
|
|||||||
@@ -24,5 +24,5 @@ done
|
|||||||
export CLASSPATH=$CLASSPATH:$lib
|
export CLASSPATH=$CLASSPATH:$lib
|
||||||
|
|
||||||
echo "$APP_HOME"
|
echo "$APP_HOME"
|
||||||
nohup java -DAPP_HOME="$APP_HOME" org.redkale.boot.Application > "$APP_HOME"/log.out &
|
nohup java -DAPP_HOME="$APP_HOME" org.redkale.boot.Application > "$APP_HOME"/logs.out &
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<application port="5050">
|
<application port="2121">
|
||||||
|
|
||||||
<!-- 详细配置说明见: http://redkale.org/redkale.html#redkale_confxml -->
|
<!-- 详细配置说明见: http://redkale.org/redkale.html#redkale_confxml -->
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<server protocol="HTTP" host="0.0.0.0" port="6060" root="root">
|
<server protocol="HTTP" port="6060">
|
||||||
|
|
||||||
<request>
|
<request>
|
||||||
<remoteaddr value="request.headers.X-RemoteAddress"/>
|
<remoteaddr value="request.headers.X-RemoteAddress"/>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
|
||||||
|
|
||||||
handlers = java.util.logging.ConsoleHandler
|
handlers = java.util.logging.ConsoleHandler
|
||||||
|
# handlers = java.util.logging.FileHandler
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
.level = FINER
|
.level = FINEST
|
||||||
|
|
||||||
java.level = INFO
|
java.level = INFO
|
||||||
javax.level = INFO
|
javax.level = INFO
|
||||||
@@ -14,11 +15,11 @@ jdk.level = INFO
|
|||||||
|
|
||||||
java.util.logging.FileHandler.level = FINER
|
java.util.logging.FileHandler.level = FINER
|
||||||
#10M
|
#10M
|
||||||
java.util.logging.FileHandler.limit = 10485760
|
java.util.logging.FileHandler.limit = 10M
|
||||||
java.util.logging.FileHandler.count = 10000
|
java.util.logging.FileHandler.count = 20
|
||||||
java.util.logging.FileHandler.encoding = UTF-8
|
java.util.logging.FileHandler.encoding = UTF-8
|
||||||
java.util.logging.FileHandler.pattern = ${APP_HOME}/logs-%m/log-%d.log
|
java.util.logging.FileHandler.pattern = ${APP_HOME}/logs-%m/log-%d.log
|
||||||
java.util.logging.FileHandler.unusual = ${APP_HOME}/logs-%m/log-warnerr-%d.log
|
java.util.logging.FileHandler.unusual = ${APP_HOME}/logs-%m/log-warnerr-%d.log
|
||||||
java.util.logging.FileHandler.append = true
|
java.util.logging.FileHandler.append = true
|
||||||
|
|
||||||
java.util.logging.ConsoleHandler.level = FINER
|
java.util.logging.ConsoleHandler.level = FINEST
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
<shared-cache-mode>ALL</shared-cache-mode>
|
<shared-cache-mode>ALL</shared-cache-mode>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/center?autoReconnect=true&characterEncoding=utf8"/>
|
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/center?autoReconnect=true&characterEncoding=utf8"/>
|
||||||
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
|
||||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||||
<property name="javax.persistence.jdbc.password" value="1234"/>
|
<property name="javax.persistence.jdbc.password" value="1234"/>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -17,7 +16,6 @@
|
|||||||
<shared-cache-mode>ALL</shared-cache-mode>
|
<shared-cache-mode>ALL</shared-cache-mode>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
|
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
|
||||||
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
|
|
||||||
<property name="javax.persistence.jdbc.user" value="system"/>
|
<property name="javax.persistence.jdbc.user" value="system"/>
|
||||||
<property name="javax.persistence.jdbc.password" value="1234"/>
|
<property name="javax.persistence.jdbc.password" value="1234"/>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -26,8 +24,7 @@
|
|||||||
<persistence-unit name="user.write" transaction-type="RESOURCE_LOCAL">
|
<persistence-unit name="user.write" transaction-type="RESOURCE_LOCAL">
|
||||||
<shared-cache-mode>ALL</shared-cache-mode>
|
<shared-cache-mode>ALL</shared-cache-mode>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/user?autoReconnect=true&characterEncoding=utf8"/>
|
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/center?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true"/>
|
||||||
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
|
||||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||||
<property name="javax.persistence.jdbc.password" value="1234"/>
|
<property name="javax.persistence.jdbc.password" value="1234"/>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.5.1</version>
|
<version>3.5.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
<compilerArgument>-parameters</compilerArgument>
|
||||||
<encoding>UTF-8</encoding>
|
<encoding>UTF-8</encoding>
|
||||||
<compilerArguments>
|
<compilerArguments>
|
||||||
<verbose />
|
<verbose />
|
||||||
|
|||||||
@@ -37,11 +37,11 @@
|
|||||||
threads: 线程总数, 默认: <group>节点数*CPU核数*2
|
threads: 线程总数, 默认: <group>节点数*CPU核数*2
|
||||||
bufferCapacity: ByteBuffer的初始化大小, 默认: 32K;
|
bufferCapacity: ByteBuffer的初始化大小, 默认: 32K;
|
||||||
bufferPoolSize: ByteBuffer池的大小,默认: 线程总数*4
|
bufferPoolSize: ByteBuffer池的大小,默认: 线程总数*4
|
||||||
readTimeoutSecond: TCP读取超时秒数, 默认为6秒, 为0表示无超时限制
|
readTimeoutSeconds: TCP读取超时秒数, 默认为6秒, 为0表示无超时限制
|
||||||
writeTimeoutSecond: TCP写入超时秒数, 默认为6秒, 为0表示无超时限制
|
writeTimeoutSeconds: TCP写入超时秒数, 默认为6秒, 为0表示无超时限制
|
||||||
strategy: 远程请求的负载均衡策略, 必须是org.redkale.net.TransportStrategy的实现类
|
strategy: 远程请求的负载均衡策略, 必须是org.redkale.net.TransportStrategy的实现类
|
||||||
-->
|
-->
|
||||||
<transport bufferCapacity="32K" bufferPoolSize="32" threads="32" readTimeoutSecond="6" writeTimeoutSecond="6"/>
|
<transport bufferCapacity="32K" bufferPoolSize="32" threads="32" readTimeoutSeconds="6" writeTimeoutSeconds="6"/>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
一个组包含多个node, 同一Service服务可以由多个进程提供,这些进程称为一个GROUP,且同一GROUP内的进程必须在同一机房或局域网内
|
一个组包含多个node, 同一Service服务可以由多个进程提供,这些进程称为一个GROUP,且同一GROUP内的进程必须在同一机房或局域网内
|
||||||
@@ -85,7 +85,9 @@
|
|||||||
如果name是mimetype.property.开头的值将会在进程启动时进行MimeType.add("yyyy", "YYYYYY")操作。
|
如果name是mimetype.property.开头的值将会在进程启动时进行MimeType.add("yyyy", "YYYYYY")操作。
|
||||||
load: 加载文件,多个用;隔开。
|
load: 加载文件,多个用;隔开。
|
||||||
默认置入的system.property.的有:
|
默认置入的system.property.的有:
|
||||||
|
System.setProperty("net.transport.poolmaxconns", "100");
|
||||||
System.setProperty("net.transport.pinginterval", "30");
|
System.setProperty("net.transport.pinginterval", "30");
|
||||||
|
System.setProperty("net.transport.checkinterval", "30");
|
||||||
System.setProperty("convert.json.tiny", "true");
|
System.setProperty("convert.json.tiny", "true");
|
||||||
System.setProperty("convert.bson.tiny", "true");
|
System.setProperty("convert.bson.tiny", "true");
|
||||||
System.setProperty("convert.json.pool.size", "128");
|
System.setProperty("convert.json.pool.size", "128");
|
||||||
@@ -114,18 +116,31 @@
|
|||||||
excludelibs: 排除lib.path与excludes中的正则表达式匹配的路径, 多个正则表达式用分号;隔开
|
excludelibs: 排除lib.path与excludes中的正则表达式匹配的路径, 多个正则表达式用分号;隔开
|
||||||
charset: 文本编码, 默认: UTF-8
|
charset: 文本编码, 默认: UTF-8
|
||||||
backlog: 默认10K
|
backlog: 默认10K
|
||||||
threads: 线程总数, 默认: CPU核数*8
|
threads: 线程数, 默认: CPU核数*32
|
||||||
maxconns:最大连接数, 小于1表示无限制, 默认: 0
|
maxconns:最大连接数, 小于1表示无限制, 默认: 0
|
||||||
maxbody: request.body最大值, 默认: 64K
|
maxbody: request.body最大值, 默认: 64K
|
||||||
bufferCapacity: ByteBuffer的初始化大小, 默认: 32K; (HTTP 2.0、WebSocket,必须要16k以上)
|
bufferCapacity: ByteBuffer的初始化大小, 默认: 32K; (HTTP 2.0、WebSocket,必须要16k以上)
|
||||||
bufferPoolSize: ByteBuffer池的大小,默认: 线程总数*4
|
bufferPoolSize: ByteBuffer池的大小,默认: 线程数*4
|
||||||
responsePoolSize: Response池的大小,默认: 线程总数*2
|
responsePoolSize: Response池的大小,默认: 线程数*2
|
||||||
readTimeoutSecond: 读操作超时秒数, 默认0, 表示永久不超时
|
aliveTimeoutSeconds: KeepAlive读操作超时秒数, 默认30, 0表示永久不超时; -1表示禁止KeepAlive
|
||||||
writeTimeoutSecond: 写操作超时秒数, 默认0, 表示永久不超时
|
readTimeoutSeconds: 读操作超时秒数, 默认0, 表示永久不超时
|
||||||
|
writeTimeoutSeconds: 写操作超时秒数, 默认0, 表示永久不超时
|
||||||
|
netimpl: ProtocolServer的实现类。TCP情况下值可以是aio或nio,默认值为aio;UDP情况下值可以是bio,默认值为bio;
|
||||||
interceptor: 启动/关闭NodeServer时被调用的拦截器实现类,必须是org.redkale.boot.NodeInterceptor的子类,默认为null
|
interceptor: 启动/关闭NodeServer时被调用的拦截器实现类,必须是org.redkale.boot.NodeInterceptor的子类,默认为null
|
||||||
-->
|
-->
|
||||||
<server protocol="HTTP" host="127.0.0.1" port="6060" root="root" lib="">
|
<server protocol="HTTP" host="127.0.0.1" port="6060" root="root" lib="">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
【节点在<server>中唯一】
|
||||||
|
value: 创建SSLContext的实现类, 可自定义,必须是org.redkale.net.SSLCreator的子类
|
||||||
|
clientauth: true/false/want
|
||||||
|
keystorepass: KEY密码
|
||||||
|
keystorefile: KEY文件
|
||||||
|
truststorepass: TRUST密码
|
||||||
|
truststorefile: TRUST文件
|
||||||
|
-->
|
||||||
|
<ssl creator=""/>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
加载所有的Service服务;
|
加载所有的Service服务;
|
||||||
在同一个进程中同一个name同一类型的Service将共用同一个实例
|
在同一个进程中同一个name同一类型的Service将共用同一个实例
|
||||||
@@ -216,26 +231,33 @@
|
|||||||
<!--
|
<!--
|
||||||
【节点在<server>中唯一】
|
【节点在<server>中唯一】
|
||||||
当Server为HTTP协议时, response节点才有效。
|
当Server为HTTP协议时, response节点才有效。
|
||||||
|
contenttype: plain值为调用finish时的ContentType; 默认值: text/plain; charset=utf-8
|
||||||
|
json值为调用finishJson时的ContentType; 默认值: application/json; charset=utf-8
|
||||||
defcookie 节点: 当response里输出的cookie没有指定domain 和path时,使用该节点的默认值。
|
defcookie 节点: 当response里输出的cookie没有指定domain 和path时,使用该节点的默认值。
|
||||||
如果addheader、setheader 的value值以request.parameters.开头则表示从request.parameters中获取对应的parameter值
|
如果addheader、setheader 的value值以request.parameters.开头则表示从request.parameters中获取对应的parameter值
|
||||||
如果addheader、setheader 的value值以request.headers.开头则表示从request.headers中获取对应的header值
|
如果addheader、setheader 的value值以request.headers.开头则表示从request.headers中获取对应的header值
|
||||||
例如下面例子是在Response输出header时添加两个header(一个addHeader, 一个setHeader)。
|
例如下面例子是在Response输出header时添加两个header(一个addHeader, 一个setHeader)。
|
||||||
options 节点: 设置了该节点却auto=true,当request的method=OPTIONS自动设置addheader、setheader并返回200状态码
|
options 节点: 设置了该节点且auto=true,当request的method=OPTIONS自动设置addheader、setheader并返回200状态码
|
||||||
|
date 节点: 设置了该节点且period有值(单位:毫秒);返回response会包含Date头信息,默认为period=0
|
||||||
|
period=0表示实时获取当前时间;
|
||||||
|
period<0表示不设置date;
|
||||||
|
period>0表示定时获取时间; 设置1000表示每秒刷新Date时间
|
||||||
-->
|
-->
|
||||||
<response>
|
<response>
|
||||||
|
<contenttype plain="text/plain; charset=utf-8" json="application/json; charset=utf-8"/>
|
||||||
<defcookie domain="" path=""/>
|
<defcookie domain="" path=""/>
|
||||||
<addheader name="Access-Control-Allow-Origin" value="request.headers.Origin" />
|
<addheader name="Access-Control-Allow-Origin" value="request.headers.Origin" />
|
||||||
<setheader name="Access-Control-Allow-Headers" value="request.headers.Access-Control-Request-Headers"/>
|
<setheader name="Access-Control-Allow-Headers" value="request.headers.Access-Control-Request-Headers"/>
|
||||||
<setheader name="Access-Control-Allow-Credentials" value="true"/>
|
<setheader name="Access-Control-Allow-Credentials" value="true"/>
|
||||||
<options auto="true" />
|
<options auto="true" />
|
||||||
|
<date period="0" />
|
||||||
</response>
|
</response>
|
||||||
<!--
|
<!--
|
||||||
【节点在<server>中唯一】
|
【节点在<server>中唯一】
|
||||||
当Server为HTTP协议时,render才有效. 指定输出引擎的实现类
|
当Server为HTTP协议时,render才有效. 指定输出引擎的实现类
|
||||||
value: 输出引擎的实现类, 必须是org.redkale.net.http.HttpRender的子类
|
value: 输出引擎的实现类, 必须是org.redkale.net.http.HttpRender的子类
|
||||||
-->
|
-->
|
||||||
<render value="org.redkalex.htel.HttpTemplateRender">
|
<render value="org.redkalex.htel.HttpTemplateRender"/>
|
||||||
</render>
|
|
||||||
<!--
|
<!--
|
||||||
【节点在<server>中唯一】
|
【节点在<server>中唯一】
|
||||||
当Server为HTTP协议时,ResourceServlet才有效. 默认存在一个有默认属性的resource-servlet节点
|
当Server为HTTP协议时,ResourceServlet才有效. 默认存在一个有默认属性的resource-servlet节点
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ javax.level = INFO
|
|||||||
com.sun.level = INFO
|
com.sun.level = INFO
|
||||||
|
|
||||||
#java.util.logging.FileHandler.level = FINE
|
#java.util.logging.FileHandler.level = FINE
|
||||||
#10M
|
|
||||||
java.util.logging.FileHandler.limit = 10485760
|
java.util.logging.FileHandler.limit = 20M
|
||||||
java.util.logging.FileHandler.count = 100
|
java.util.logging.FileHandler.count = 100
|
||||||
java.util.logging.FileHandler.encoding = UTF-8
|
java.util.logging.FileHandler.encoding = UTF-8
|
||||||
java.util.logging.FileHandler.pattern = ${APP_HOME}/logs-%m/log-%d.log
|
java.util.logging.FileHandler.pattern = ${APP_HOME}/logs-%m/log-%d.log
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
-->
|
-->
|
||||||
<property name="javax.persistence.datasource" value="org.redkale.source.DataJdbcSource"/>
|
<property name="javax.persistence.datasource" value="org.redkale.source.DataJdbcSource"/>
|
||||||
<!--
|
<!--
|
||||||
是否开启缓存(标记为@Cacheable的Entity类),值目前只支持两种: ALL: 所有开启缓存。 NONE: 关闭所有缓存
|
是否开启缓存(标记为@Cacheable的Entity类),值目前只支持两种: ALL: 所有开启缓存。 NONE: 关闭所有缓存, 非NONE字样统一视为ALL
|
||||||
-->
|
-->
|
||||||
<property name="javax.persistence.cachemode" value="ALL"/>
|
<property name="javax.persistence.cachemode" value="ALL"/>
|
||||||
|
|
||||||
@@ -20,12 +20,15 @@
|
|||||||
org.mariadb.jdbc.Driver —————— org.mariadb.jdbc.MySQLDataSource
|
org.mariadb.jdbc.Driver —————— org.mariadb.jdbc.MySQLDataSource
|
||||||
org.postgresql.Driver —————— org.postgresql.ds.PGConnectionPoolDataSource
|
org.postgresql.Driver —————— org.postgresql.ds.PGConnectionPoolDataSource
|
||||||
com.mysql.jdbc.Driver —————— com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
|
com.mysql.jdbc.Driver —————— com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
|
||||||
|
com.mysql.cj.jdbc.Driver —————— com.mysql.cj.jdbc.MysqlConnectionPoolDataSource
|
||||||
oracle.jdbc.driver.OracleDriver —————— oracle.jdbc.pool.OracleConnectionPoolDataSource
|
oracle.jdbc.driver.OracleDriver —————— oracle.jdbc.pool.OracleConnectionPoolDataSource
|
||||||
com.microsoft.sqlserver.jdbc.SQLServerDriver —————— com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
|
com.microsoft.sqlserver.jdbc.SQLServerDriver —————— com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
|
||||||
|
org.h2.Driver —————— org.h2.jdbcx.JdbcDataSource
|
||||||
因此 com.mysql.jdbc.Driver 会被自动转换成 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
|
因此 com.mysql.jdbc.Driver 会被自动转换成 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
|
||||||
并且如果JDBC驱动是以上几个版本,javax.persistence.jdbc.driver属性都可以省略,Redkale会根据javax.persistence.jdbc.url的值来识别驱动
|
并且如果JDBC驱动是以上几个版本,javax.persistence.jdbc.driver属性都可以省略,Redkale会根据javax.persistence.jdbc.url的值来识别驱动
|
||||||
-->
|
|
||||||
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
||||||
|
<property name="javax.persistence.jdbc.source" value="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource"/>
|
||||||
|
-->
|
||||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||||
<property name="javax.persistence.jdbc.password" value="123456"/>
|
<property name="javax.persistence.jdbc.password" value="123456"/>
|
||||||
|
|
||||||
@@ -47,7 +50,6 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<!-- jdbc:mysql://127.0.0.1:3306/dbim?autoReconnect=true&autoReconnectForPools=true&characterEncoding=utf8 -->
|
<!-- jdbc:mysql://127.0.0.1:3306/dbim?autoReconnect=true&autoReconnectForPools=true&characterEncoding=utf8 -->
|
||||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/dbim?characterEncoding=utf8"/>
|
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/dbim?characterEncoding=utf8"/>
|
||||||
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
|
||||||
<property name="javax.persistence.jdbc.user" value="root"/>
|
<property name="javax.persistence.jdbc.user" value="root"/>
|
||||||
<property name="javax.persistence.jdbc.password" value="123456"/>
|
<property name="javax.persistence.jdbc.password" value="123456"/>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ module org.redkale {
|
|||||||
requires java.logging;
|
requires java.logging;
|
||||||
requires java.xml;
|
requires java.xml;
|
||||||
requires java.sql;
|
requires java.sql;
|
||||||
requires java.sql.rowset;
|
|
||||||
|
|
||||||
requires jdk.unsupported; //sun.misc.Unsafe
|
requires jdk.unsupported; //sun.misc.Unsafe
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public abstract class AnnotationVisitor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The ASM API version implemented by this visitor. The value of this field
|
* The ASM API version implemented by this visitor. The value of this field
|
||||||
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
protected final int api;
|
protected final int api;
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ public abstract class AnnotationVisitor {
|
|||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
public AnnotationVisitor(final int api) {
|
public AnnotationVisitor(final int api) {
|
||||||
this(api, null);
|
this(api, null);
|
||||||
@@ -96,15 +96,12 @@ public abstract class AnnotationVisitor {
|
|||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
* @param av
|
* @param av
|
||||||
* the annotation visitor to which this visitor must delegate
|
* the annotation visitor to which this visitor must delegate
|
||||||
* method calls. May be null.
|
* method calls. May be null.
|
||||||
*/
|
*/
|
||||||
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
|
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
|
||||||
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.av = av;
|
this.av = av;
|
||||||
}
|
}
|
||||||
@@ -118,7 +115,7 @@ public abstract class AnnotationVisitor {
|
|||||||
* the actual value, whose type must be {@link Byte},
|
* the actual value, whose type must be {@link Byte},
|
||||||
* {@link Boolean}, {@link Character}, {@link Short},
|
* {@link Boolean}, {@link Character}, {@link Short},
|
||||||
* {@link Integer} , {@link Long}, {@link Float}, {@link Double},
|
* {@link Integer} , {@link Long}, {@link Float}, {@link Double},
|
||||||
* {@link String} or {@link Type} or OBJECT or ARRAY sort. This
|
* {@link String} or {@link Type} of OBJECT or ARRAY sort. This
|
||||||
* value can also be an array of byte, boolean, short, char, int,
|
* value can also be an array of byte, boolean, short, char, int,
|
||||||
* long, float or double values (this is equivalent to using
|
* long, float or double values (this is equivalent to using
|
||||||
* {@link #visitArray visitArray} and visiting each array element
|
* {@link #visitArray visitArray} and visiting each array element
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ final class AnnotationWriter extends AnnotationVisitor {
|
|||||||
*/
|
*/
|
||||||
AnnotationWriter(final ClassWriter cw, final boolean named,
|
AnnotationWriter(final ClassWriter cw, final boolean named,
|
||||||
final ByteVector bv, final ByteVector parent, final int offset) {
|
final ByteVector bv, final ByteVector parent, final int offset) {
|
||||||
super(Opcodes.ASM5);
|
super(Opcodes.ASM6);
|
||||||
this.cw = cw;
|
this.cw = cw;
|
||||||
this.named = named;
|
this.named = named;
|
||||||
this.bv = bv;
|
this.bv = bv;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ package org.redkale.asm;
|
|||||||
* @author Eric Bruneton
|
* @author Eric Bruneton
|
||||||
* @author Eugene Kuleshov
|
* @author Eugene Kuleshov
|
||||||
*/
|
*/
|
||||||
public class Attribute {
|
class Attribute {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of this attribute.
|
* The type of this attribute.
|
||||||
|
|||||||
@@ -72,31 +72,6 @@ import java.io.InputStream;
|
|||||||
*/
|
*/
|
||||||
public class ClassReader {
|
public class ClassReader {
|
||||||
|
|
||||||
/**
|
|
||||||
* True to enable signatures support.
|
|
||||||
*/
|
|
||||||
static final boolean SIGNATURES = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True to enable annotations support.
|
|
||||||
*/
|
|
||||||
static final boolean ANNOTATIONS = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True to enable stack map frames support.
|
|
||||||
*/
|
|
||||||
static final boolean FRAMES = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True to enable bytecode writing support.
|
|
||||||
*/
|
|
||||||
static final boolean WRITER = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True to enable JSR_W and GOTO_W support.
|
|
||||||
*/
|
|
||||||
static final boolean RESIZE = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag to skip method code. If this class is set <code>CODE</code>
|
* Flag to skip method code. If this class is set <code>CODE</code>
|
||||||
* attribute won't be visited. This can be used, for example, to retrieve
|
* attribute won't be visited. This can be used, for example, to retrieve
|
||||||
@@ -133,6 +108,21 @@ public class ClassReader {
|
|||||||
*/
|
*/
|
||||||
public static final int EXPAND_FRAMES = 8;
|
public static final int EXPAND_FRAMES = 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag to expand the ASM pseudo instructions into an equivalent sequence of
|
||||||
|
* standard bytecode instructions. When resolving a forward jump it may
|
||||||
|
* happen that the signed 2 bytes offset reserved for it is not sufficient
|
||||||
|
* to store the bytecode offset. In this case the jump instruction is
|
||||||
|
* replaced with a temporary ASM pseudo instruction using an unsigned 2
|
||||||
|
* bytes offset (see Label#resolve). This internal flag is used to re-read
|
||||||
|
* classes containing such instructions, in order to replace them with
|
||||||
|
* standard instructions. In addition, when this flag is used, GOTO_W and
|
||||||
|
* JSR_W are <i>not</i> converted into GOTO and JSR, to make sure that
|
||||||
|
* infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and
|
||||||
|
* converted back to a GOTO_W in ClassWriter cannot occur.
|
||||||
|
*/
|
||||||
|
static final int EXPAND_ASM_INSNS = 256;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class to be parsed. <i>The content of this array must not be
|
* The class to be parsed. <i>The content of this array must not be
|
||||||
* modified. This field is intended for {@link Attribute} sub classes, and
|
* modified. This field is intended for {@link Attribute} sub classes, and
|
||||||
@@ -195,8 +185,8 @@ public class ClassReader {
|
|||||||
public ClassReader(final byte[] b, final int off, final int len) {
|
public ClassReader(final byte[] b, final int off, final int len) {
|
||||||
this.b = b;
|
this.b = b;
|
||||||
// checks the class version
|
// checks the class version
|
||||||
if (readShort(off + 6) > Opcodes.V1_9) {
|
if (readShort(off + 6) > Opcodes.V10) {
|
||||||
throw new IllegalArgumentException();
|
//throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
// parses the constant pool
|
// parses the constant pool
|
||||||
items = new int[readUnsignedShort(off + 8)];
|
items = new int[readUnsignedShort(off + 8)];
|
||||||
@@ -234,6 +224,8 @@ public class ClassReader {
|
|||||||
// case ClassWriter.CLASS:
|
// case ClassWriter.CLASS:
|
||||||
// case ClassWriter.STR:
|
// case ClassWriter.STR:
|
||||||
// case ClassWriter.MTYPE
|
// case ClassWriter.MTYPE
|
||||||
|
// case ClassWriter.PACKAGE:
|
||||||
|
// case ClassWriter.MODULE:
|
||||||
default:
|
default:
|
||||||
size = 3;
|
size = 3;
|
||||||
break;
|
break;
|
||||||
@@ -377,7 +369,9 @@ public class ClassReader {
|
|||||||
break;
|
break;
|
||||||
// case ClassWriter.STR:
|
// case ClassWriter.STR:
|
||||||
// case ClassWriter.CLASS:
|
// case ClassWriter.CLASS:
|
||||||
// case ClassWriter.MTYPE
|
// case ClassWriter.MTYPE:
|
||||||
|
// case ClassWriter.MODULE:
|
||||||
|
// case ClassWriter.PACKAGE:
|
||||||
default:
|
default:
|
||||||
item.set(tag, readUTF8(index, buf), null, null);
|
item.set(tag, readUTF8(index, buf), null, null);
|
||||||
break;
|
break;
|
||||||
@@ -584,11 +578,14 @@ public class ClassReader {
|
|||||||
String enclosingOwner = null;
|
String enclosingOwner = null;
|
||||||
String enclosingName = null;
|
String enclosingName = null;
|
||||||
String enclosingDesc = null;
|
String enclosingDesc = null;
|
||||||
|
String moduleMainClass = null;
|
||||||
int anns = 0;
|
int anns = 0;
|
||||||
int ianns = 0;
|
int ianns = 0;
|
||||||
int tanns = 0;
|
int tanns = 0;
|
||||||
int itanns = 0;
|
int itanns = 0;
|
||||||
int innerClasses = 0;
|
int innerClasses = 0;
|
||||||
|
int module = 0;
|
||||||
|
int packages = 0;
|
||||||
Attribute attributes = null;
|
Attribute attributes = null;
|
||||||
|
|
||||||
u = getAttributes();
|
u = getAttributes();
|
||||||
@@ -607,13 +604,11 @@ public class ClassReader {
|
|||||||
enclosingName = readUTF8(items[item], c);
|
enclosingName = readUTF8(items[item], c);
|
||||||
enclosingDesc = readUTF8(items[item] + 2, c);
|
enclosingDesc = readUTF8(items[item] + 2, c);
|
||||||
}
|
}
|
||||||
} else if (SIGNATURES && "Signature".equals(attrName)) {
|
} else if ("Signature".equals(attrName)) {
|
||||||
signature = readUTF8(u + 8, c);
|
signature = readUTF8(u + 8, c);
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeVisibleAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeVisibleAnnotations".equals(attrName)) {
|
|
||||||
anns = u + 8;
|
anns = u + 8;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
|
|
||||||
tanns = u + 8;
|
tanns = u + 8;
|
||||||
} else if ("Deprecated".equals(attrName)) {
|
} else if ("Deprecated".equals(attrName)) {
|
||||||
access |= Opcodes.ACC_DEPRECATED;
|
access |= Opcodes.ACC_DEPRECATED;
|
||||||
@@ -623,12 +618,16 @@ public class ClassReader {
|
|||||||
} else if ("SourceDebugExtension".equals(attrName)) {
|
} else if ("SourceDebugExtension".equals(attrName)) {
|
||||||
int len = readInt(u + 4);
|
int len = readInt(u + 4);
|
||||||
sourceDebug = readUTF(u + 8, len, new char[len]);
|
sourceDebug = readUTF(u + 8, len, new char[len]);
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
|
|
||||||
ianns = u + 8;
|
ianns = u + 8;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
|
|
||||||
itanns = u + 8;
|
itanns = u + 8;
|
||||||
|
} else if ("Module".equals(attrName)) {
|
||||||
|
module = u + 8;
|
||||||
|
} else if ("ModuleMainClass".equals(attrName)) {
|
||||||
|
moduleMainClass = readClass(u + 8, c);
|
||||||
|
} else if ("ModulePackages".equals(attrName)) {
|
||||||
|
packages = u + 10;
|
||||||
} else if ("BootstrapMethods".equals(attrName)) {
|
} else if ("BootstrapMethods".equals(attrName)) {
|
||||||
int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
|
int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
|
||||||
for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
|
for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
|
||||||
@@ -657,6 +656,12 @@ public class ClassReader {
|
|||||||
classVisitor.visitSource(sourceFile, sourceDebug);
|
classVisitor.visitSource(sourceFile, sourceDebug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// visits the module info and associated attributes
|
||||||
|
if (module != 0) {
|
||||||
|
readModule(classVisitor, context, module,
|
||||||
|
moduleMainClass, packages);
|
||||||
|
}
|
||||||
|
|
||||||
// visits the outer class
|
// visits the outer class
|
||||||
if (enclosingOwner != null) {
|
if (enclosingOwner != null) {
|
||||||
classVisitor.visitOuterClass(enclosingOwner, enclosingName,
|
classVisitor.visitOuterClass(enclosingOwner, enclosingName,
|
||||||
@@ -664,19 +669,19 @@ public class ClassReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// visits the class annotations and type annotations
|
// visits the class annotations and type annotations
|
||||||
if (ANNOTATIONS && anns != 0) {
|
if (anns != 0) {
|
||||||
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
classVisitor.visitAnnotation(readUTF8(v, c), true));
|
classVisitor.visitAnnotation(readUTF8(v, c), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && ianns != 0) {
|
if (ianns != 0) {
|
||||||
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
classVisitor.visitAnnotation(readUTF8(v, c), false));
|
classVisitor.visitAnnotation(readUTF8(v, c), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && tanns != 0) {
|
if (tanns != 0) {
|
||||||
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
|
||||||
v = readAnnotationTarget(context, v);
|
v = readAnnotationTarget(context, v);
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
@@ -684,7 +689,7 @@ public class ClassReader {
|
|||||||
context.typePath, readUTF8(v, c), true));
|
context.typePath, readUTF8(v, c), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && itanns != 0) {
|
if (itanns != 0) {
|
||||||
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
|
||||||
v = readAnnotationTarget(context, v);
|
v = readAnnotationTarget(context, v);
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
@@ -726,6 +731,120 @@ public class ClassReader {
|
|||||||
classVisitor.visitEnd();
|
classVisitor.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the module attribute and visit it.
|
||||||
|
*
|
||||||
|
* @param classVisitor
|
||||||
|
* the current class visitor
|
||||||
|
* @param context
|
||||||
|
* information about the class being parsed.
|
||||||
|
* @param u
|
||||||
|
* start offset of the module attribute in the class file.
|
||||||
|
* @param mainClass
|
||||||
|
* name of the main class of a module or null.
|
||||||
|
* @param packages
|
||||||
|
* start offset of the concealed package attribute.
|
||||||
|
*/
|
||||||
|
private void readModule(final ClassVisitor classVisitor,
|
||||||
|
final Context context, int u,
|
||||||
|
final String mainClass, int packages) {
|
||||||
|
|
||||||
|
char[] buffer = context.buffer;
|
||||||
|
|
||||||
|
// reads module name, flags and version
|
||||||
|
String name = readModule(u, buffer);
|
||||||
|
int flags = readUnsignedShort(u + 2);
|
||||||
|
String version = readUTF8(u + 4, buffer);
|
||||||
|
u += 6;
|
||||||
|
|
||||||
|
ModuleVisitor mv = classVisitor.visitModule(name, flags, version);
|
||||||
|
if (mv == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// module attributes (main class, packages)
|
||||||
|
if (mainClass != null) {
|
||||||
|
mv.visitMainClass(mainClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packages != 0) {
|
||||||
|
for (int i = readUnsignedShort(packages - 2); i > 0; --i) {
|
||||||
|
String packaze = readPackage(packages, buffer);
|
||||||
|
mv.visitPackage(packaze);
|
||||||
|
packages += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads requires
|
||||||
|
u += 2;
|
||||||
|
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
|
||||||
|
String module = readModule(u, buffer);
|
||||||
|
int access = readUnsignedShort(u + 2);
|
||||||
|
String requireVersion = readUTF8(u + 4, buffer);
|
||||||
|
mv.visitRequire(module, access, requireVersion);
|
||||||
|
u += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads exports
|
||||||
|
u += 2;
|
||||||
|
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
|
||||||
|
String export = readPackage(u, buffer);
|
||||||
|
int access = readUnsignedShort(u + 2);
|
||||||
|
int exportToCount = readUnsignedShort(u + 4);
|
||||||
|
u += 6;
|
||||||
|
String[] tos = null;
|
||||||
|
if (exportToCount != 0) {
|
||||||
|
tos = new String[exportToCount];
|
||||||
|
for (int j = 0; j < tos.length; ++j) {
|
||||||
|
tos[j] = readModule(u, buffer);
|
||||||
|
u += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mv.visitExport(export, access, tos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads opens
|
||||||
|
u += 2;
|
||||||
|
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
|
||||||
|
String open = readPackage(u, buffer);
|
||||||
|
int access = readUnsignedShort(u + 2);
|
||||||
|
int openToCount = readUnsignedShort(u + 4);
|
||||||
|
u += 6;
|
||||||
|
String[] tos = null;
|
||||||
|
if (openToCount != 0) {
|
||||||
|
tos = new String[openToCount];
|
||||||
|
for (int j = 0; j < tos.length; ++j) {
|
||||||
|
tos[j] = readModule(u, buffer);
|
||||||
|
u += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mv.visitOpen(open, access, tos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read uses
|
||||||
|
u += 2;
|
||||||
|
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
|
||||||
|
mv.visitUse(readClass(u, buffer));
|
||||||
|
u += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read provides
|
||||||
|
u += 2;
|
||||||
|
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
|
||||||
|
String service = readClass(u, buffer);
|
||||||
|
int provideWithCount = readUnsignedShort(u + 2);
|
||||||
|
u += 4;
|
||||||
|
String[] withs = new String[provideWithCount];
|
||||||
|
for (int j = 0; j < withs.length; ++j) {
|
||||||
|
withs[j] = readClass(u, buffer);
|
||||||
|
u += 2;
|
||||||
|
}
|
||||||
|
mv.visitProvide(service, withs);
|
||||||
|
}
|
||||||
|
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a field and makes the given visitor visit it.
|
* Reads a field and makes the given visitor visit it.
|
||||||
*
|
*
|
||||||
@@ -762,24 +881,20 @@ public class ClassReader {
|
|||||||
if ("ConstantValue".equals(attrName)) {
|
if ("ConstantValue".equals(attrName)) {
|
||||||
int item = readUnsignedShort(u + 8);
|
int item = readUnsignedShort(u + 8);
|
||||||
value = item == 0 ? null : readConst(item, c);
|
value = item == 0 ? null : readConst(item, c);
|
||||||
} else if (SIGNATURES && "Signature".equals(attrName)) {
|
} else if ("Signature".equals(attrName)) {
|
||||||
signature = readUTF8(u + 8, c);
|
signature = readUTF8(u + 8, c);
|
||||||
} else if ("Deprecated".equals(attrName)) {
|
} else if ("Deprecated".equals(attrName)) {
|
||||||
access |= Opcodes.ACC_DEPRECATED;
|
access |= Opcodes.ACC_DEPRECATED;
|
||||||
} else if ("Synthetic".equals(attrName)) {
|
} else if ("Synthetic".equals(attrName)) {
|
||||||
access |= Opcodes.ACC_SYNTHETIC
|
access |= Opcodes.ACC_SYNTHETIC
|
||||||
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
|
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeVisibleAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeVisibleAnnotations".equals(attrName)) {
|
|
||||||
anns = u + 8;
|
anns = u + 8;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
|
|
||||||
tanns = u + 8;
|
tanns = u + 8;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
|
|
||||||
ianns = u + 8;
|
ianns = u + 8;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
|
|
||||||
itanns = u + 8;
|
itanns = u + 8;
|
||||||
} else {
|
} else {
|
||||||
Attribute attr = readAttribute(context.attrs, attrName, u + 8,
|
Attribute attr = readAttribute(context.attrs, attrName, u + 8,
|
||||||
@@ -801,19 +916,19 @@ public class ClassReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// visits the field annotations and type annotations
|
// visits the field annotations and type annotations
|
||||||
if (ANNOTATIONS && anns != 0) {
|
if (anns != 0) {
|
||||||
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
fv.visitAnnotation(readUTF8(v, c), true));
|
fv.visitAnnotation(readUTF8(v, c), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && ianns != 0) {
|
if (ianns != 0) {
|
||||||
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
fv.visitAnnotation(readUTF8(v, c), false));
|
fv.visitAnnotation(readUTF8(v, c), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && tanns != 0) {
|
if (tanns != 0) {
|
||||||
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
|
||||||
v = readAnnotationTarget(context, v);
|
v = readAnnotationTarget(context, v);
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
@@ -821,7 +936,7 @@ public class ClassReader {
|
|||||||
context.typePath, readUTF8(v, c), true));
|
context.typePath, readUTF8(v, c), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && itanns != 0) {
|
if (itanns != 0) {
|
||||||
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
|
||||||
v = readAnnotationTarget(context, v);
|
v = readAnnotationTarget(context, v);
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
@@ -895,32 +1010,26 @@ public class ClassReader {
|
|||||||
exceptions[j] = readClass(exception, c);
|
exceptions[j] = readClass(exception, c);
|
||||||
exception += 2;
|
exception += 2;
|
||||||
}
|
}
|
||||||
} else if (SIGNATURES && "Signature".equals(attrName)) {
|
} else if ("Signature".equals(attrName)) {
|
||||||
signature = readUTF8(u + 8, c);
|
signature = readUTF8(u + 8, c);
|
||||||
} else if ("Deprecated".equals(attrName)) {
|
} else if ("Deprecated".equals(attrName)) {
|
||||||
context.access |= Opcodes.ACC_DEPRECATED;
|
context.access |= Opcodes.ACC_DEPRECATED;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeVisibleAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeVisibleAnnotations".equals(attrName)) {
|
|
||||||
anns = u + 8;
|
anns = u + 8;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
|
|
||||||
tanns = u + 8;
|
tanns = u + 8;
|
||||||
} else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
|
} else if ("AnnotationDefault".equals(attrName)) {
|
||||||
dann = u + 8;
|
dann = u + 8;
|
||||||
} else if ("Synthetic".equals(attrName)) {
|
} else if ("Synthetic".equals(attrName)) {
|
||||||
context.access |= Opcodes.ACC_SYNTHETIC
|
context.access |= Opcodes.ACC_SYNTHETIC
|
||||||
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
|
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
|
|
||||||
ianns = u + 8;
|
ianns = u + 8;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
|
|
||||||
itanns = u + 8;
|
itanns = u + 8;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeVisibleParameterAnnotations".equals(attrName)) {
|
|
||||||
mpanns = u + 8;
|
mpanns = u + 8;
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
|
|
||||||
impanns = u + 8;
|
impanns = u + 8;
|
||||||
} else if ("MethodParameters".equals(attrName)) {
|
} else if ("MethodParameters".equals(attrName)) {
|
||||||
methodParameters = u + 8;
|
methodParameters = u + 8;
|
||||||
@@ -953,7 +1062,7 @@ public class ClassReader {
|
|||||||
* access, name and descriptor can have been changed, this is not
|
* access, name and descriptor can have been changed, this is not
|
||||||
* important since they are not copied as is from the reader).
|
* important since they are not copied as is from the reader).
|
||||||
*/
|
*/
|
||||||
if (WRITER && mv instanceof MethodWriter) {
|
if (mv instanceof MethodWriter) {
|
||||||
MethodWriter mw = (MethodWriter) mv;
|
MethodWriter mw = (MethodWriter) mv;
|
||||||
if (mw.cw.cr == this && signature == mw.signature) {
|
if (mw.cw.cr == this && signature == mw.signature) {
|
||||||
boolean sameExceptions = false;
|
boolean sameExceptions = false;
|
||||||
@@ -990,26 +1099,26 @@ public class ClassReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// visits the method annotations
|
// visits the method annotations
|
||||||
if (ANNOTATIONS && dann != 0) {
|
if (dann != 0) {
|
||||||
AnnotationVisitor dv = mv.visitAnnotationDefault();
|
AnnotationVisitor dv = mv.visitAnnotationDefault();
|
||||||
readAnnotationValue(dann, c, null, dv);
|
readAnnotationValue(dann, c, null, dv);
|
||||||
if (dv != null) {
|
if (dv != null) {
|
||||||
dv.visitEnd();
|
dv.visitEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && anns != 0) {
|
if (anns != 0) {
|
||||||
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
mv.visitAnnotation(readUTF8(v, c), true));
|
mv.visitAnnotation(readUTF8(v, c), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && ianns != 0) {
|
if (ianns != 0) {
|
||||||
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
mv.visitAnnotation(readUTF8(v, c), false));
|
mv.visitAnnotation(readUTF8(v, c), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && tanns != 0) {
|
if (tanns != 0) {
|
||||||
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
|
||||||
v = readAnnotationTarget(context, v);
|
v = readAnnotationTarget(context, v);
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
@@ -1017,7 +1126,7 @@ public class ClassReader {
|
|||||||
context.typePath, readUTF8(v, c), true));
|
context.typePath, readUTF8(v, c), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && itanns != 0) {
|
if (itanns != 0) {
|
||||||
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
|
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
|
||||||
v = readAnnotationTarget(context, v);
|
v = readAnnotationTarget(context, v);
|
||||||
v = readAnnotationValues(v + 2, c, true,
|
v = readAnnotationValues(v + 2, c, true,
|
||||||
@@ -1025,10 +1134,10 @@ public class ClassReader {
|
|||||||
context.typePath, readUTF8(v, c), false));
|
context.typePath, readUTF8(v, c), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && mpanns != 0) {
|
if (mpanns != 0) {
|
||||||
readParameterAnnotations(mv, context, mpanns, true);
|
readParameterAnnotations(mv, context, mpanns, true);
|
||||||
}
|
}
|
||||||
if (ANNOTATIONS && impanns != 0) {
|
if (impanns != 0) {
|
||||||
readParameterAnnotations(mv, context, impanns, false);
|
readParameterAnnotations(mv, context, impanns, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1075,7 +1184,7 @@ public class ClassReader {
|
|||||||
int codeStart = u;
|
int codeStart = u;
|
||||||
int codeEnd = u + codeLength;
|
int codeEnd = u + codeLength;
|
||||||
Label[] labels = context.labels = new Label[codeLength + 2];
|
Label[] labels = context.labels = new Label[codeLength + 2];
|
||||||
readLabel(codeLength + 1, labels);
|
createLabel(codeLength + 1, labels);
|
||||||
while (u < codeEnd) {
|
while (u < codeEnd) {
|
||||||
int offset = u - codeStart;
|
int offset = u - codeStart;
|
||||||
int opcode = b[u] & 0xFF;
|
int opcode = b[u] & 0xFF;
|
||||||
@@ -1085,11 +1194,16 @@ public class ClassReader {
|
|||||||
u += 1;
|
u += 1;
|
||||||
break;
|
break;
|
||||||
case ClassWriter.LABEL_INSN:
|
case ClassWriter.LABEL_INSN:
|
||||||
readLabel(offset + readShort(u + 1), labels);
|
createLabel(offset + readShort(u + 1), labels);
|
||||||
|
u += 3;
|
||||||
|
break;
|
||||||
|
case ClassWriter.ASM_LABEL_INSN:
|
||||||
|
createLabel(offset + readUnsignedShort(u + 1), labels);
|
||||||
u += 3;
|
u += 3;
|
||||||
break;
|
break;
|
||||||
case ClassWriter.LABELW_INSN:
|
case ClassWriter.LABELW_INSN:
|
||||||
readLabel(offset + readInt(u + 1), labels);
|
case ClassWriter.ASM_LABELW_INSN:
|
||||||
|
createLabel(offset + readInt(u + 1), labels);
|
||||||
u += 5;
|
u += 5;
|
||||||
break;
|
break;
|
||||||
case ClassWriter.WIDE_INSN:
|
case ClassWriter.WIDE_INSN:
|
||||||
@@ -1104,9 +1218,9 @@ public class ClassReader {
|
|||||||
// skips 0 to 3 padding bytes
|
// skips 0 to 3 padding bytes
|
||||||
u = u + 4 - (offset & 3);
|
u = u + 4 - (offset & 3);
|
||||||
// reads instruction
|
// reads instruction
|
||||||
readLabel(offset + readInt(u), labels);
|
createLabel(offset + readInt(u), labels);
|
||||||
for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
|
for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
|
||||||
readLabel(offset + readInt(u + 12), labels);
|
createLabel(offset + readInt(u + 12), labels);
|
||||||
u += 4;
|
u += 4;
|
||||||
}
|
}
|
||||||
u += 12;
|
u += 12;
|
||||||
@@ -1115,9 +1229,9 @@ public class ClassReader {
|
|||||||
// skips 0 to 3 padding bytes
|
// skips 0 to 3 padding bytes
|
||||||
u = u + 4 - (offset & 3);
|
u = u + 4 - (offset & 3);
|
||||||
// reads instruction
|
// reads instruction
|
||||||
readLabel(offset + readInt(u), labels);
|
createLabel(offset + readInt(u), labels);
|
||||||
for (int i = readInt(u + 4); i > 0; --i) {
|
for (int i = readInt(u + 4); i > 0; --i) {
|
||||||
readLabel(offset + readInt(u + 12), labels);
|
createLabel(offset + readInt(u + 12), labels);
|
||||||
u += 8;
|
u += 8;
|
||||||
}
|
}
|
||||||
u += 8;
|
u += 8;
|
||||||
@@ -1147,9 +1261,9 @@ public class ClassReader {
|
|||||||
|
|
||||||
// reads the try catch entries to find the labels, and also visits them
|
// reads the try catch entries to find the labels, and also visits them
|
||||||
for (int i = readUnsignedShort(u); i > 0; --i) {
|
for (int i = readUnsignedShort(u); i > 0; --i) {
|
||||||
Label start = readLabel(readUnsignedShort(u + 2), labels);
|
Label start = createLabel(readUnsignedShort(u + 2), labels);
|
||||||
Label end = readLabel(readUnsignedShort(u + 4), labels);
|
Label end = createLabel(readUnsignedShort(u + 4), labels);
|
||||||
Label handler = readLabel(readUnsignedShort(u + 6), labels);
|
Label handler = createLabel(readUnsignedShort(u + 6), labels);
|
||||||
String type = readUTF8(items[readUnsignedShort(u + 8)], c);
|
String type = readUTF8(items[readUnsignedShort(u + 8)], c);
|
||||||
mv.visitTryCatchBlock(start, end, handler, type);
|
mv.visitTryCatchBlock(start, end, handler, type);
|
||||||
u += 8;
|
u += 8;
|
||||||
@@ -1180,13 +1294,9 @@ public class ClassReader {
|
|||||||
varTable = u + 8;
|
varTable = u + 8;
|
||||||
for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
|
for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
|
||||||
int label = readUnsignedShort(v + 10);
|
int label = readUnsignedShort(v + 10);
|
||||||
if (labels[label] == null) {
|
createDebugLabel(label, labels);
|
||||||
readLabel(label, labels).status |= Label.DEBUG;
|
|
||||||
}
|
|
||||||
label += readUnsignedShort(v + 12);
|
label += readUnsignedShort(v + 12);
|
||||||
if (labels[label] == null) {
|
createDebugLabel(label, labels);
|
||||||
readLabel(label, labels).status |= Label.DEBUG;
|
|
||||||
}
|
|
||||||
v += 10;
|
v += 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1196,9 +1306,7 @@ public class ClassReader {
|
|||||||
if ((context.flags & SKIP_DEBUG) == 0) {
|
if ((context.flags & SKIP_DEBUG) == 0) {
|
||||||
for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
|
for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
|
||||||
int label = readUnsignedShort(v + 10);
|
int label = readUnsignedShort(v + 10);
|
||||||
if (labels[label] == null) {
|
createDebugLabel(label, labels);
|
||||||
readLabel(label, labels).status |= Label.DEBUG;
|
|
||||||
}
|
|
||||||
Label l = labels[label];
|
Label l = labels[label];
|
||||||
while (l.line > 0) {
|
while (l.line > 0) {
|
||||||
if (l.next == null) {
|
if (l.next == null) {
|
||||||
@@ -1210,17 +1318,15 @@ public class ClassReader {
|
|||||||
v += 4;
|
v += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
|
|
||||||
tanns = readTypeAnnotations(mv, context, u + 8, true);
|
tanns = readTypeAnnotations(mv, context, u + 8, true);
|
||||||
ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
|
ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
|
||||||
: readUnsignedShort(tanns[0] + 1);
|
: readUnsignedShort(tanns[0] + 1);
|
||||||
} else if (ANNOTATIONS
|
} else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
|
||||||
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
|
|
||||||
itanns = readTypeAnnotations(mv, context, u + 8, false);
|
itanns = readTypeAnnotations(mv, context, u + 8, false);
|
||||||
nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
|
nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
|
||||||
: readUnsignedShort(itanns[0] + 1);
|
: readUnsignedShort(itanns[0] + 1);
|
||||||
} else if (FRAMES && "StackMapTable".equals(attrName)) {
|
} else if ("StackMapTable".equals(attrName)) {
|
||||||
if ((context.flags & SKIP_FRAMES) == 0) {
|
if ((context.flags & SKIP_FRAMES) == 0) {
|
||||||
stackMap = u + 10;
|
stackMap = u + 10;
|
||||||
stackMapSize = readInt(u + 4);
|
stackMapSize = readInt(u + 4);
|
||||||
@@ -1244,7 +1350,7 @@ public class ClassReader {
|
|||||||
* this by parsing the stack map table without a full decoding
|
* this by parsing the stack map table without a full decoding
|
||||||
* (see below).
|
* (see below).
|
||||||
*/
|
*/
|
||||||
} else if (FRAMES && "StackMap".equals(attrName)) {
|
} else if ("StackMap".equals(attrName)) {
|
||||||
if ((context.flags & SKIP_FRAMES) == 0) {
|
if ((context.flags & SKIP_FRAMES) == 0) {
|
||||||
zip = false;
|
zip = false;
|
||||||
stackMap = u + 10;
|
stackMap = u + 10;
|
||||||
@@ -1273,7 +1379,7 @@ public class ClassReader {
|
|||||||
u += 2;
|
u += 2;
|
||||||
|
|
||||||
// generates the first (implicit) stack map frame
|
// generates the first (implicit) stack map frame
|
||||||
if (FRAMES && stackMap != 0) {
|
if (stackMap != 0) {
|
||||||
/*
|
/*
|
||||||
* for the first explicit frame the offset is not offset_delta + 1
|
* for the first explicit frame the offset is not offset_delta + 1
|
||||||
* but only offset_delta; setting the implicit frame offset to -1
|
* but only offset_delta; setting the implicit frame offset to -1
|
||||||
@@ -1306,14 +1412,31 @@ public class ClassReader {
|
|||||||
int v = readUnsignedShort(i + 1);
|
int v = readUnsignedShort(i + 1);
|
||||||
if (v >= 0 && v < codeLength) {
|
if (v >= 0 && v < codeLength) {
|
||||||
if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
|
if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
|
||||||
readLabel(v, labels);
|
createLabel(v, labels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((context.flags & EXPAND_ASM_INSNS) != 0
|
||||||
|
&& (context.flags & EXPAND_FRAMES) != 0) {
|
||||||
|
// Expanding the ASM pseudo instructions can introduce F_INSERT
|
||||||
|
// frames, even if the method does not currently have any frame.
|
||||||
|
// Also these inserted frames must be computed by simulating the
|
||||||
|
// effect of the bytecode instructions one by one, starting from the
|
||||||
|
// first one and the last existing frame (or the implicit first
|
||||||
|
// one). Finally, due to the way MethodWriter computes this (with
|
||||||
|
// the compute = INSERTED_FRAMES option), MethodWriter needs to know
|
||||||
|
// maxLocals before the first instruction is visited. For all these
|
||||||
|
// reasons we always visit the implicit first frame in this case
|
||||||
|
// (passing only maxLocals - the rest can be and is computed in
|
||||||
|
// MethodWriter).
|
||||||
|
mv.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null);
|
||||||
|
}
|
||||||
|
|
||||||
// visits the instructions
|
// visits the instructions
|
||||||
|
int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0;
|
||||||
|
boolean insertFrame = false;
|
||||||
u = codeStart;
|
u = codeStart;
|
||||||
while (u < codeEnd) {
|
while (u < codeEnd) {
|
||||||
int offset = u - codeStart;
|
int offset = u - codeStart;
|
||||||
@@ -1334,7 +1457,7 @@ public class ClassReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// visits the frame for this offset, if any
|
// visits the frame for this offset, if any
|
||||||
while (FRAMES && frame != null
|
while (frame != null
|
||||||
&& (frame.offset == offset || frame.offset == -1)) {
|
&& (frame.offset == offset || frame.offset == -1)) {
|
||||||
// if there is a frame for this offset, makes the visitor visit
|
// if there is a frame for this offset, makes the visitor visit
|
||||||
// it, and reads the next frame if there is one.
|
// it, and reads the next frame if there is one.
|
||||||
@@ -1346,6 +1469,9 @@ public class ClassReader {
|
|||||||
mv.visitFrame(frame.mode, frame.localDiff, frame.local,
|
mv.visitFrame(frame.mode, frame.localDiff, frame.local,
|
||||||
frame.stackCount, frame.stack);
|
frame.stackCount, frame.stack);
|
||||||
}
|
}
|
||||||
|
// if there is already a frame for this offset, there is no
|
||||||
|
// need to insert a new one.
|
||||||
|
insertFrame = false;
|
||||||
}
|
}
|
||||||
if (frameCount > 0) {
|
if (frameCount > 0) {
|
||||||
stackMap = readFrame(stackMap, zip, unzip, frame);
|
stackMap = readFrame(stackMap, zip, unzip, frame);
|
||||||
@@ -1354,6 +1480,13 @@ public class ClassReader {
|
|||||||
frame = null;
|
frame = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// inserts a frame for this offset, if requested by setting
|
||||||
|
// insertFrame to true during the previous iteration. The actual
|
||||||
|
// frame content will be computed in MethodWriter.
|
||||||
|
if (insertFrame) {
|
||||||
|
mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
|
||||||
|
insertFrame = false;
|
||||||
|
}
|
||||||
|
|
||||||
// visits the instruction at this offset
|
// visits the instruction at this offset
|
||||||
int opcode = b[u] & 0xFF;
|
int opcode = b[u] & 0xFF;
|
||||||
@@ -1378,9 +1511,47 @@ public class ClassReader {
|
|||||||
u += 3;
|
u += 3;
|
||||||
break;
|
break;
|
||||||
case ClassWriter.LABELW_INSN:
|
case ClassWriter.LABELW_INSN:
|
||||||
mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]);
|
mv.visitJumpInsn(opcode + opcodeDelta, labels[offset
|
||||||
|
+ readInt(u + 1)]);
|
||||||
u += 5;
|
u += 5;
|
||||||
break;
|
break;
|
||||||
|
case ClassWriter.ASM_LABEL_INSN: {
|
||||||
|
// changes temporary opcodes 202 to 217 (inclusive), 218
|
||||||
|
// and 219 to IFEQ ... JSR (inclusive), IFNULL and
|
||||||
|
// IFNONNULL
|
||||||
|
opcode = opcode < 218 ? opcode - 49 : opcode - 20;
|
||||||
|
Label target = labels[offset + readUnsignedShort(u + 1)];
|
||||||
|
// replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
|
||||||
|
// <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is
|
||||||
|
// the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
|
||||||
|
// and where <L> designates the instruction just after
|
||||||
|
// the GOTO_W.
|
||||||
|
if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
|
||||||
|
mv.visitJumpInsn(opcode + 33, target);
|
||||||
|
} else {
|
||||||
|
opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
|
||||||
|
: opcode ^ 1;
|
||||||
|
Label endif = createLabel(offset + 3, labels);
|
||||||
|
mv.visitJumpInsn(opcode, endif);
|
||||||
|
mv.visitJumpInsn(200, target); // GOTO_W
|
||||||
|
// endif designates the instruction just after GOTO_W,
|
||||||
|
// and is visited as part of the next instruction. Since
|
||||||
|
// it is a jump target, we need to insert a frame here.
|
||||||
|
insertFrame = true;
|
||||||
|
}
|
||||||
|
u += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ClassWriter.ASM_LABELW_INSN: {
|
||||||
|
// replaces the pseudo GOTO_W instruction with a real one.
|
||||||
|
mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]);
|
||||||
|
// The instruction just after is a jump target (because pseudo
|
||||||
|
// GOTO_W are used in patterns IFNOTxxx <L> GOTO_W <l> L:...,
|
||||||
|
// see MethodWriter), so we need to insert a frame here.
|
||||||
|
insertFrame = true;
|
||||||
|
u += 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ClassWriter.WIDE_INSN:
|
case ClassWriter.WIDE_INSN:
|
||||||
opcode = b[u + 1] & 0xFF;
|
opcode = b[u + 1] & 0xFF;
|
||||||
if (opcode == Opcodes.IINC) {
|
if (opcode == Opcodes.IINC) {
|
||||||
@@ -1636,8 +1807,8 @@ public class ClassReader {
|
|||||||
for (int j = readUnsignedShort(u + 1); j > 0; --j) {
|
for (int j = readUnsignedShort(u + 1); j > 0; --j) {
|
||||||
int start = readUnsignedShort(u + 3);
|
int start = readUnsignedShort(u + 3);
|
||||||
int length = readUnsignedShort(u + 5);
|
int length = readUnsignedShort(u + 5);
|
||||||
readLabel(start, context.labels);
|
createLabel(start, context.labels);
|
||||||
readLabel(start + length, context.labels);
|
createLabel(start + length, context.labels);
|
||||||
u += 6;
|
u += 6;
|
||||||
}
|
}
|
||||||
u += 3;
|
u += 3;
|
||||||
@@ -1716,8 +1887,8 @@ public class ClassReader {
|
|||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
int start = readUnsignedShort(u);
|
int start = readUnsignedShort(u);
|
||||||
int length = readUnsignedShort(u + 2);
|
int length = readUnsignedShort(u + 2);
|
||||||
context.start[i] = readLabel(start, context.labels);
|
context.start[i] = createLabel(start, context.labels);
|
||||||
context.end[i] = readLabel(start + length, context.labels);
|
context.end[i] = createLabel(start + length, context.labels);
|
||||||
context.index[i] = readUnsignedShort(u + 4);
|
context.index[i] = readUnsignedShort(u + 4);
|
||||||
u += 6;
|
u += 6;
|
||||||
}
|
}
|
||||||
@@ -2137,7 +2308,7 @@ public class ClassReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
frame.offset += delta + 1;
|
frame.offset += delta + 1;
|
||||||
readLabel(frame.offset, labels);
|
createLabel(frame.offset, labels);
|
||||||
return stackMap;
|
return stackMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2190,7 +2361,7 @@ public class ClassReader {
|
|||||||
v += 2;
|
v += 2;
|
||||||
break;
|
break;
|
||||||
default: // Uninitialized
|
default: // Uninitialized
|
||||||
frame[index] = readLabel(readUnsignedShort(v), labels);
|
frame[index] = createLabel(readUnsignedShort(v), labels);
|
||||||
v += 2;
|
v += 2;
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
@@ -2216,6 +2387,39 @@ public class ClassReader {
|
|||||||
return labels[offset];
|
return labels[offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a label without the Label.DEBUG flag set, for the given offset.
|
||||||
|
* The label is created with a call to {@link #readLabel} and its
|
||||||
|
* Label.DEBUG flag is cleared.
|
||||||
|
*
|
||||||
|
* @param offset
|
||||||
|
* a bytecode offset in a method.
|
||||||
|
* @param labels
|
||||||
|
* the already created labels, indexed by their offset.
|
||||||
|
* @return a Label without the Label.DEBUG flag set.
|
||||||
|
*/
|
||||||
|
private Label createLabel(int offset, Label[] labels) {
|
||||||
|
Label label = readLabel(offset, labels);
|
||||||
|
label.status &= ~Label.DEBUG;
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a label with the Label.DEBUG flag set, if there is no already
|
||||||
|
* existing label for the given offset (otherwise does nothing). The label
|
||||||
|
* is created with a call to {@link #readLabel}.
|
||||||
|
*
|
||||||
|
* @param offset
|
||||||
|
* a bytecode offset in a method.
|
||||||
|
* @param labels
|
||||||
|
* the already created labels, indexed by their offset.
|
||||||
|
*/
|
||||||
|
private void createDebugLabel(int offset, Label[] labels) {
|
||||||
|
if (labels[offset] == null) {
|
||||||
|
readLabel(offset, labels).status |= Label.DEBUG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the start index of the attribute_info structure of this class.
|
* Returns the start index of the attribute_info structure of this class.
|
||||||
*
|
*
|
||||||
@@ -2470,6 +2674,20 @@ public class ClassReader {
|
|||||||
return new String(buf, 0, strLen);
|
return new String(buf, 0, strLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a stringish constant item (CONSTANT_Class, CONSTANT_String,
|
||||||
|
* CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package
|
||||||
|
* @param index
|
||||||
|
* @param buf
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String readStringish(final int index, final char[] buf) {
|
||||||
|
// computes the start index of the item in b
|
||||||
|
// and reads the CONSTANT_Utf8 item designated by
|
||||||
|
// the first two bytes of this item
|
||||||
|
return readUTF8(items[readUnsignedShort(index)], buf);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a class constant pool item in {@link #b b}. <i>This method is
|
* Reads a class constant pool item in {@link #b b}. <i>This method is
|
||||||
* intended for {@link Attribute} sub classes, and is normally not needed by
|
* intended for {@link Attribute} sub classes, and is normally not needed by
|
||||||
@@ -2484,44 +2702,41 @@ public class ClassReader {
|
|||||||
* @return the String corresponding to the specified class item.
|
* @return the String corresponding to the specified class item.
|
||||||
*/
|
*/
|
||||||
public String readClass(final int index, final char[] buf) {
|
public String readClass(final int index, final char[] buf) {
|
||||||
// computes the start index of the CONSTANT_Class item in b
|
return readStringish(index, buf);
|
||||||
// and reads the CONSTANT_Utf8 item designated by
|
|
||||||
// the first two bytes of this CONSTANT_Class item
|
|
||||||
return readUTF8(items[readUnsignedShort(index)], buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a CONSTANT_Module_info item in {@code b}. This method is intended
|
* Reads a module constant pool item in {@link #b b}. <i>This method is
|
||||||
* for {@link Attribute} sub classes, and is normally not needed by class
|
* intended for {@link Attribute} sub classes, and is normally not needed by
|
||||||
* generators or adapters.
|
* class generators or adapters.</i>
|
||||||
*
|
*
|
||||||
* @param index
|
* @param index
|
||||||
* the start index of an unsigned short value in {@link #b b},
|
* the start index of an unsigned short value in {@link #b b},
|
||||||
* whose value is the index of a module constant pool item.
|
* whose value is the index of a module constant pool item.
|
||||||
* @param buf
|
* @param buf
|
||||||
* buffer to be used to read the item. This buffer must be
|
* buffer to be used to read the item. This buffer must be
|
||||||
* sufficiently large. It is not automatically resized.
|
* sufficiently large. It is not automatically resized.
|
||||||
* @return the String corresponding to the specified module item.
|
* @return the String corresponding to the specified module item.
|
||||||
*/
|
*/
|
||||||
public String readModule(int index, char[] buf) {
|
public String readModule(final int index, final char[] buf) {
|
||||||
return readUTF8(items[readUnsignedShort(index)], buf);
|
return readStringish(index, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a CONSTANT_Package_info item in {@code b}. This method is
|
* Reads a module constant pool item in {@link #b b}. <i>This method is
|
||||||
* intended for {@link Attribute} sub slasses, and is normally not needed
|
* intended for {@link Attribute} sub classes, and is normally not needed by
|
||||||
* by class generators or adapters.
|
* class generators or adapters.</i>
|
||||||
*
|
*
|
||||||
* @param index
|
* @param index
|
||||||
* the start index of an unsigned short value in {@link #b b},
|
* the start index of an unsigned short value in {@link #b b},
|
||||||
* whose value is the index of a package constant pool item.
|
* whose value is the index of a module constant pool item.
|
||||||
* @param buf
|
* @param buf
|
||||||
* buffer to be used to read the item. This buffer must be
|
* buffer to be used to read the item. This buffer must be
|
||||||
* sufficiently large. It is not automatically resized.
|
* sufficiently large. It is not automatically resized.
|
||||||
* @return the String corresponding to the specified package item.
|
* @return the String corresponding to the specified module item.
|
||||||
*/
|
*/
|
||||||
public String readPackage(int index, char[] buf) {
|
public String readPackage(final int index, final char[] buf) {
|
||||||
return readUTF8(items[readUnsignedShort(index)], buf);
|
return readStringish(index, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2550,8 +2765,6 @@ public class ClassReader {
|
|||||||
case ClassWriter.DOUBLE:
|
case ClassWriter.DOUBLE:
|
||||||
return Double.longBitsToDouble(readLong(index));
|
return Double.longBitsToDouble(readLong(index));
|
||||||
case ClassWriter.CLASS:
|
case ClassWriter.CLASS:
|
||||||
case ClassWriter.MODULE:
|
|
||||||
case ClassWriter.PACKAGE:
|
|
||||||
return Type.getObjectType(readUTF8(index, buf));
|
return Type.getObjectType(readUTF8(index, buf));
|
||||||
case ClassWriter.STR:
|
case ClassWriter.STR:
|
||||||
return readUTF8(index, buf);
|
return readUTF8(index, buf);
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ package org.redkale.asm;
|
|||||||
/**
|
/**
|
||||||
* A visitor to visit a Java class. The methods of this class must be called in
|
* A visitor to visit a Java class. The methods of this class must be called in
|
||||||
* the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
|
* the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
|
||||||
* <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
|
* <tt>visitModule</tt> ][ <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
|
||||||
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
|
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
|
||||||
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
|
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
|
||||||
* <tt>visitEnd</tt>.
|
* <tt>visitEnd</tt>.
|
||||||
@@ -72,7 +72,7 @@ public abstract class ClassVisitor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The ASM API version implemented by this visitor. The value of this field
|
* The ASM API version implemented by this visitor. The value of this field
|
||||||
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
protected final int api;
|
protected final int api;
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ public abstract class ClassVisitor {
|
|||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
public ClassVisitor(final int api) {
|
public ClassVisitor(final int api) {
|
||||||
this(api, null);
|
this(api, null);
|
||||||
@@ -98,15 +98,12 @@ public abstract class ClassVisitor {
|
|||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
* @param cv
|
* @param cv
|
||||||
* the class visitor to which this visitor must delegate method
|
* the class visitor to which this visitor must delegate method
|
||||||
* calls. May be null.
|
* calls. May be null.
|
||||||
*/
|
*/
|
||||||
public ClassVisitor(final int api, final ClassVisitor cv) {
|
public ClassVisitor(final int api, final ClassVisitor cv) {
|
||||||
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.cv = cv;
|
this.cv = cv;
|
||||||
}
|
}
|
||||||
@@ -160,6 +157,28 @@ public abstract class ClassVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the module corresponding to the class.
|
||||||
|
* @param name
|
||||||
|
* module name
|
||||||
|
* @param access
|
||||||
|
* module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
|
||||||
|
* and {@code ACC_MANDATED}.
|
||||||
|
* @param version
|
||||||
|
* module version or null.
|
||||||
|
* @return a visitor to visit the module values, or <tt>null</tt> if
|
||||||
|
* this visitor is not interested in visiting this module.
|
||||||
|
*/
|
||||||
|
public ModuleVisitor visitModule(String name, int access, String version) {
|
||||||
|
if (api < Opcodes.ASM6) {
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
if (cv != null) {
|
||||||
|
return cv.visitModule(name, access, version);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visits the enclosing class of the class. This method must be called only
|
* Visits the enclosing class of the class. This method must be called only
|
||||||
* if the class has an enclosing class.
|
* if the class has an enclosing class.
|
||||||
@@ -222,9 +241,6 @@ public abstract class ClassVisitor {
|
|||||||
*/
|
*/
|
||||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||||
TypePath typePath, String desc, boolean visible) {
|
TypePath typePath, String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (cv != null) {
|
if (cv != null) {
|
||||||
return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
* {@link MethodVisitor#visitFrame} method are ignored, and the stack map
|
* {@link MethodVisitor#visitFrame} method are ignored, and the stack map
|
||||||
* frames are recomputed from the methods bytecode. The arguments of the
|
* frames are recomputed from the methods bytecode. The arguments of the
|
||||||
* {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
|
* {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
|
||||||
* recomputed from the bytecode. In other words, computeFrames implies
|
* recomputed from the bytecode. In other words, COMPUTE_FRAMES implies
|
||||||
* computeMaxs.
|
* COMPUTE_MAXS.
|
||||||
*
|
*
|
||||||
* @see #ClassWriter(int)
|
* @see #ClassWriter(int)
|
||||||
*/
|
*/
|
||||||
@@ -196,6 +196,27 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
*/
|
*/
|
||||||
static final int WIDE_INSN = 17;
|
static final int WIDE_INSN = 17;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the ASM pseudo instructions with an unsigned 2 bytes offset
|
||||||
|
* label (see Label#resolve).
|
||||||
|
*/
|
||||||
|
static final int ASM_LABEL_INSN = 18;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the ASM pseudo instructions with a 4 bytes offset label.
|
||||||
|
*/
|
||||||
|
static final int ASM_LABELW_INSN = 19;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a frame inserted between already existing frames. This kind of
|
||||||
|
* frame can only be used if the frame content can be computed from the
|
||||||
|
* previous existing frame and from the instructions between this existing
|
||||||
|
* frame and the inserted one, without any knowledge of the type hierarchy.
|
||||||
|
* This kind of frame is only used when an unconditional jump is inserted in
|
||||||
|
* a method while expanding an ASM pseudo instruction (see ClassReader).
|
||||||
|
*/
|
||||||
|
static final int F_INSERT = 256;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The instruction types of all JVM opcodes.
|
* The instruction types of all JVM opcodes.
|
||||||
*/
|
*/
|
||||||
@@ -284,7 +305,7 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
/**
|
/**
|
||||||
* The base value for all CONSTANT_MethodHandle constant pool items.
|
* The base value for all CONSTANT_MethodHandle constant pool items.
|
||||||
* Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
|
* Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
|
||||||
* different items.
|
* different items (from 21 to 29).
|
||||||
*/
|
*/
|
||||||
static final int HANDLE_BASE = 20;
|
static final int HANDLE_BASE = 20;
|
||||||
|
|
||||||
@@ -433,6 +454,11 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
*/
|
*/
|
||||||
private ByteVector sourceDebug;
|
private ByteVector sourceDebug;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The module attribute of this class.
|
||||||
|
*/
|
||||||
|
private ModuleWriter moduleWriter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constant pool item that contains the name of the enclosing class of
|
* The constant pool item that contains the name of the enclosing class of
|
||||||
* this class.
|
* this class.
|
||||||
@@ -523,25 +549,19 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
MethodWriter lastMethod;
|
MethodWriter lastMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <tt>true</tt> if the maximum stack size and number of local variables
|
* Indicates what must be automatically computed.
|
||||||
* must be automatically computed.
|
*
|
||||||
|
* @see MethodWriter#compute
|
||||||
*/
|
*/
|
||||||
private boolean computeMaxs;
|
private int compute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <tt>true</tt> if the stack map frames must be recomputed from scratch.
|
* <tt>true</tt> if some methods have wide forward jumps using ASM pseudo
|
||||||
|
* instructions, which need to be expanded into sequences of standard
|
||||||
|
* bytecode instructions. In this case the class is re-read and re-written
|
||||||
|
* with a ClassReader -> ClassWriter chain to perform this transformation.
|
||||||
*/
|
*/
|
||||||
private boolean computeFrames;
|
boolean hasAsmInsns;
|
||||||
|
|
||||||
/**
|
|
||||||
* <tt>true</tt> if the stack map tables of this class are invalid. The
|
|
||||||
* {@link MethodWriter#resizeInstructions} method cannot transform existing
|
|
||||||
* stack map tables, and so produces potentially invalid classes when it is
|
|
||||||
* executed. In this case the class is reread and rewritten with the
|
|
||||||
* {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
|
|
||||||
* stack map tables when this option is used).
|
|
||||||
*/
|
|
||||||
boolean invalidFrames;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Static initializer
|
// Static initializer
|
||||||
@@ -552,11 +572,11 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
*/
|
*/
|
||||||
static {
|
static {
|
||||||
int i;
|
int i;
|
||||||
byte[] b = new byte[220];
|
byte[] b = new byte[221];
|
||||||
String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
|
String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
|
||||||
+ "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
+ "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||||
+ "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
|
+ "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
|
||||||
+ "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ";
|
+ "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSST";
|
||||||
for (i = 0; i < b.length; ++i) {
|
for (i = 0; i < b.length; ++i) {
|
||||||
b[i] = (byte) (s.charAt(i) - 'A');
|
b[i] = (byte) (s.charAt(i) - 'A');
|
||||||
}
|
}
|
||||||
@@ -610,8 +630,9 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
// // temporary opcodes used internally by ASM - see Label and
|
// // temporary opcodes used internally by ASM - see Label and
|
||||||
// MethodWriter
|
// MethodWriter
|
||||||
// for (i = 202; i < 220; ++i) {
|
// for (i = 202; i < 220; ++i) {
|
||||||
// b[i] = LABEL_INSN;
|
// b[i] = ASM_LABEL_INSN;
|
||||||
// }
|
// }
|
||||||
|
// b[220] = ASM_LABELW_INSN;
|
||||||
//
|
//
|
||||||
// // LDC(_W) instructions
|
// // LDC(_W) instructions
|
||||||
// b[Constants.LDC] = LDC_INSN;
|
// b[Constants.LDC] = LDC_INSN;
|
||||||
@@ -644,7 +665,7 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
* {@link #COMPUTE_FRAMES}.
|
* {@link #COMPUTE_FRAMES}.
|
||||||
*/
|
*/
|
||||||
public ClassWriter(final int flags) {
|
public ClassWriter(final int flags) {
|
||||||
super(Opcodes.ASM5);
|
super(Opcodes.ASM6);
|
||||||
index = 1;
|
index = 1;
|
||||||
pool = new ByteVector();
|
pool = new ByteVector();
|
||||||
items = new Item[256];
|
items = new Item[256];
|
||||||
@@ -653,8 +674,9 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
key2 = new Item();
|
key2 = new Item();
|
||||||
key3 = new Item();
|
key3 = new Item();
|
||||||
key4 = new Item();
|
key4 = new Item();
|
||||||
this.computeMaxs = (flags & COMPUTE_MAXS) != 0;
|
this.compute = (flags & COMPUTE_FRAMES) != 0 ? MethodWriter.FRAMES
|
||||||
this.computeFrames = (flags & COMPUTE_FRAMES) != 0;
|
: ((flags & COMPUTE_MAXS) != 0 ? MethodWriter.MAXS
|
||||||
|
: MethodWriter.NOTHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -684,9 +706,9 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
* @param flags
|
* @param flags
|
||||||
* option flags that can be used to modify the default behavior
|
* option flags that can be used to modify the default behavior
|
||||||
* of this class. <i>These option flags do not affect methods
|
* of this class. <i>These option flags do not affect methods
|
||||||
* that are copied as is in the new class. This means that the
|
* that are copied as is in the new class. This means that
|
||||||
* maximum stack size nor the stack frames will be computed for
|
* neither the maximum stack size nor the stack frames will be
|
||||||
* these methods</i>. See {@link #COMPUTE_MAXS},
|
* computed for these methods</i>. See {@link #COMPUTE_MAXS},
|
||||||
* {@link #COMPUTE_FRAMES}.
|
* {@link #COMPUTE_FRAMES}.
|
||||||
*/
|
*/
|
||||||
public ClassWriter(final ClassReader classReader, final int flags) {
|
public ClassWriter(final ClassReader classReader, final int flags) {
|
||||||
@@ -705,9 +727,9 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
final String[] interfaces) {
|
final String[] interfaces) {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.access = access;
|
this.access = access;
|
||||||
this.name = (name == null) ? 0 : newClass(name);
|
this.name = newClass(name);
|
||||||
thisName = name;
|
thisName = name;
|
||||||
if (ClassReader.SIGNATURES && signature != null) {
|
if (signature != null) {
|
||||||
this.signature = newUTF8(signature);
|
this.signature = newUTF8(signature);
|
||||||
}
|
}
|
||||||
this.superName = superName == null ? 0 : newClass(superName);
|
this.superName = superName == null ? 0 : newClass(superName);
|
||||||
@@ -731,6 +753,14 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ModuleVisitor visitModule(final String name,
|
||||||
|
final int access, final String version) {
|
||||||
|
return moduleWriter = new ModuleWriter(this,
|
||||||
|
newModule(name), access,
|
||||||
|
version == null ? 0 : newUTF8(version));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void visitOuterClass(final String owner, final String name,
|
public final void visitOuterClass(final String owner, final String name,
|
||||||
final String desc) {
|
final String desc) {
|
||||||
@@ -743,9 +773,6 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public final AnnotationVisitor visitAnnotation(final String desc,
|
public final AnnotationVisitor visitAnnotation(final String desc,
|
||||||
final boolean visible) {
|
final boolean visible) {
|
||||||
if (!ClassReader.ANNOTATIONS) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ByteVector bv = new ByteVector();
|
ByteVector bv = new ByteVector();
|
||||||
// write type, and reserve space for values count
|
// write type, and reserve space for values count
|
||||||
bv.putShort(newUTF8(desc)).putShort(0);
|
bv.putShort(newUTF8(desc)).putShort(0);
|
||||||
@@ -763,9 +790,6 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public final AnnotationVisitor visitTypeAnnotation(int typeRef,
|
public final AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||||
TypePath typePath, final String desc, final boolean visible) {
|
TypePath typePath, final String desc, final boolean visible) {
|
||||||
if (!ClassReader.ANNOTATIONS) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ByteVector bv = new ByteVector();
|
ByteVector bv = new ByteVector();
|
||||||
// write target_type and target_info
|
// write target_type and target_info
|
||||||
AnnotationWriter.putTarget(typeRef, typePath, bv);
|
AnnotationWriter.putTarget(typeRef, typePath, bv);
|
||||||
@@ -805,7 +829,7 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
// and equality tests). If so we store the index of this inner class
|
// and equality tests). If so we store the index of this inner class
|
||||||
// entry (plus one) in intVal. This hack allows duplicate detection in
|
// entry (plus one) in intVal. This hack allows duplicate detection in
|
||||||
// O(1) time.
|
// O(1) time.
|
||||||
Item nameItem = newClassItem(name);
|
Item nameItem = newStringishItem(CLASS, name);
|
||||||
if (nameItem.intVal == 0) {
|
if (nameItem.intVal == 0) {
|
||||||
++innerClassesCount;
|
++innerClassesCount;
|
||||||
innerClasses.putShort(nameItem.index);
|
innerClasses.putShort(nameItem.index);
|
||||||
@@ -830,7 +854,7 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
public final MethodVisitor visitMethod(final int access, final String name,
|
public final MethodVisitor visitMethod(final int access, final String name,
|
||||||
final String desc, final String signature, final String[] exceptions) {
|
final String desc, final String signature, final String[] exceptions) {
|
||||||
return new MethodWriter(this, access, name, desc, signature,
|
return new MethodWriter(this, access, name, desc, signature,
|
||||||
exceptions, computeMaxs, computeFrames);
|
exceptions, compute);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -874,7 +898,7 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
size += 8 + bootstrapMethods.length;
|
size += 8 + bootstrapMethods.length;
|
||||||
newUTF8("BootstrapMethods");
|
newUTF8("BootstrapMethods");
|
||||||
}
|
}
|
||||||
if (ClassReader.SIGNATURES && signature != 0) {
|
if (signature != 0) {
|
||||||
++attributeCount;
|
++attributeCount;
|
||||||
size += 8;
|
size += 8;
|
||||||
newUTF8("Signature");
|
newUTF8("Signature");
|
||||||
@@ -912,26 +936,31 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
size += 8 + innerClasses.length;
|
size += 8 + innerClasses.length;
|
||||||
newUTF8("InnerClasses");
|
newUTF8("InnerClasses");
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && anns != null) {
|
if (anns != null) {
|
||||||
++attributeCount;
|
++attributeCount;
|
||||||
size += 8 + anns.getSize();
|
size += 8 + anns.getSize();
|
||||||
newUTF8("RuntimeVisibleAnnotations");
|
newUTF8("RuntimeVisibleAnnotations");
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && ianns != null) {
|
if (ianns != null) {
|
||||||
++attributeCount;
|
++attributeCount;
|
||||||
size += 8 + ianns.getSize();
|
size += 8 + ianns.getSize();
|
||||||
newUTF8("RuntimeInvisibleAnnotations");
|
newUTF8("RuntimeInvisibleAnnotations");
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && tanns != null) {
|
if (tanns != null) {
|
||||||
++attributeCount;
|
++attributeCount;
|
||||||
size += 8 + tanns.getSize();
|
size += 8 + tanns.getSize();
|
||||||
newUTF8("RuntimeVisibleTypeAnnotations");
|
newUTF8("RuntimeVisibleTypeAnnotations");
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && itanns != null) {
|
if (itanns != null) {
|
||||||
++attributeCount;
|
++attributeCount;
|
||||||
size += 8 + itanns.getSize();
|
size += 8 + itanns.getSize();
|
||||||
newUTF8("RuntimeInvisibleTypeAnnotations");
|
newUTF8("RuntimeInvisibleTypeAnnotations");
|
||||||
}
|
}
|
||||||
|
if (moduleWriter != null) {
|
||||||
|
attributeCount += 1 + moduleWriter.attributeCount;
|
||||||
|
size += 6 + moduleWriter.size + moduleWriter.attributesSize;
|
||||||
|
newUTF8("Module");
|
||||||
|
}
|
||||||
if (attrs != null) {
|
if (attrs != null) {
|
||||||
attributeCount += attrs.getCount();
|
attributeCount += attrs.getCount();
|
||||||
size += attrs.getSize(this, null, 0, -1, -1);
|
size += attrs.getSize(this, null, 0, -1, -1);
|
||||||
@@ -968,7 +997,7 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
bootstrapMethodsCount);
|
bootstrapMethodsCount);
|
||||||
out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
|
out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
|
||||||
}
|
}
|
||||||
if (ClassReader.SIGNATURES && signature != 0) {
|
if (signature != 0) {
|
||||||
out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
|
out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
|
||||||
}
|
}
|
||||||
if (sourceFile != 0) {
|
if (sourceFile != 0) {
|
||||||
@@ -979,6 +1008,11 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
|
out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
|
||||||
out.putByteArray(sourceDebug.data, 0, len);
|
out.putByteArray(sourceDebug.data, 0, len);
|
||||||
}
|
}
|
||||||
|
if (moduleWriter != null) {
|
||||||
|
out.putShort(newUTF8("Module"));
|
||||||
|
moduleWriter.put(out);
|
||||||
|
moduleWriter.putAttributes(out);
|
||||||
|
}
|
||||||
if (enclosingMethodOwner != 0) {
|
if (enclosingMethodOwner != 0) {
|
||||||
out.putShort(newUTF8("EnclosingMethod")).putInt(4);
|
out.putShort(newUTF8("EnclosingMethod")).putInt(4);
|
||||||
out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
|
out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
|
||||||
@@ -997,41 +1031,46 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
|
out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
|
||||||
out.putByteArray(innerClasses.data, 0, innerClasses.length);
|
out.putByteArray(innerClasses.data, 0, innerClasses.length);
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && anns != null) {
|
if (anns != null) {
|
||||||
out.putShort(newUTF8("RuntimeVisibleAnnotations"));
|
out.putShort(newUTF8("RuntimeVisibleAnnotations"));
|
||||||
anns.put(out);
|
anns.put(out);
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && ianns != null) {
|
if (ianns != null) {
|
||||||
out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
|
out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
|
||||||
ianns.put(out);
|
ianns.put(out);
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && tanns != null) {
|
if (tanns != null) {
|
||||||
out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
|
out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
|
||||||
tanns.put(out);
|
tanns.put(out);
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && itanns != null) {
|
if (itanns != null) {
|
||||||
out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
|
out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
|
||||||
itanns.put(out);
|
itanns.put(out);
|
||||||
}
|
}
|
||||||
if (attrs != null) {
|
if (attrs != null) {
|
||||||
attrs.put(this, null, 0, -1, -1, out);
|
attrs.put(this, null, 0, -1, -1, out);
|
||||||
}
|
}
|
||||||
if (invalidFrames) {
|
if (hasAsmInsns) {
|
||||||
|
boolean hasFrames = false;
|
||||||
|
mb = firstMethod;
|
||||||
|
while (mb != null) {
|
||||||
|
hasFrames |= mb.frameCount > 0;
|
||||||
|
mb = (MethodWriter) mb.mv;
|
||||||
|
}
|
||||||
anns = null;
|
anns = null;
|
||||||
ianns = null;
|
ianns = null;
|
||||||
attrs = null;
|
attrs = null;
|
||||||
innerClassesCount = 0;
|
moduleWriter = null;
|
||||||
innerClasses = null;
|
|
||||||
bootstrapMethodsCount = 0;
|
|
||||||
bootstrapMethods = null;
|
|
||||||
firstField = null;
|
firstField = null;
|
||||||
lastField = null;
|
lastField = null;
|
||||||
firstMethod = null;
|
firstMethod = null;
|
||||||
lastMethod = null;
|
lastMethod = null;
|
||||||
computeMaxs = false;
|
compute =
|
||||||
computeFrames = true;
|
hasFrames ? MethodWriter.INSERTED_FRAMES : MethodWriter.NOTHING;
|
||||||
invalidFrames = false;
|
hasAsmInsns = false;
|
||||||
new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES);
|
new ClassReader(out.data).accept(this,
|
||||||
|
(hasFrames ? ClassReader.EXPAND_FRAMES : 0)
|
||||||
|
| ClassReader.EXPAND_ASM_INSNS);
|
||||||
return toByteArray();
|
return toByteArray();
|
||||||
}
|
}
|
||||||
return out.data;
|
return out.data;
|
||||||
@@ -1078,16 +1117,16 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
double val = ((Double) cst).doubleValue();
|
double val = ((Double) cst).doubleValue();
|
||||||
return newDouble(val);
|
return newDouble(val);
|
||||||
} else if (cst instanceof String) {
|
} else if (cst instanceof String) {
|
||||||
return newString((String) cst);
|
return newStringishItem(STR, (String) cst);
|
||||||
} else if (cst instanceof Type) {
|
} else if (cst instanceof Type) {
|
||||||
Type t = (Type) cst;
|
Type t = (Type) cst;
|
||||||
int s = t.getSort();
|
int s = t.getSort();
|
||||||
if (s == Type.OBJECT) {
|
if (s == Type.OBJECT) {
|
||||||
return newClassItem(t.getInternalName());
|
return newStringishItem(CLASS, t.getInternalName());
|
||||||
} else if (s == Type.METHOD) {
|
} else if (s == Type.METHOD) {
|
||||||
return newMethodTypeItem(t.getDescriptor());
|
return newStringishItem(MTYPE, t.getDescriptor());
|
||||||
} else { // s == primitive type or array
|
} else { // s == primitive type or array
|
||||||
return newClassItem(t.getDescriptor());
|
return newStringishItem(CLASS, t.getDescriptor());
|
||||||
}
|
}
|
||||||
} else if (cst instanceof Handle) {
|
} else if (cst instanceof Handle) {
|
||||||
Handle h = (Handle) cst;
|
Handle h = (Handle) cst;
|
||||||
@@ -1136,20 +1175,21 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a class reference to the constant pool of the class being build.
|
* Adds a string reference, a class reference, a method type, a module
|
||||||
|
* or a package to the constant pool of the class being build.
|
||||||
* Does nothing if the constant pool already contains a similar item.
|
* Does nothing if the constant pool already contains a similar item.
|
||||||
* <i>This method is intended for {@link Attribute} sub classes, and is
|
|
||||||
* normally not needed by class generators or adapters.</i>
|
|
||||||
*
|
*
|
||||||
|
* @param type
|
||||||
|
* a type among STR, CLASS, MTYPE, MODULE or PACKAGE
|
||||||
* @param value
|
* @param value
|
||||||
* the internal name of the class.
|
* string value of the reference.
|
||||||
* @return a new or already existing class reference item.
|
* @return a new or already existing reference item.
|
||||||
*/
|
*/
|
||||||
Item newClassItem(final String value) {
|
Item newStringishItem(final int type, final String value) {
|
||||||
key2.set(CLASS, value, null, null);
|
key2.set(type, value, null, null);
|
||||||
Item result = get(key2);
|
Item result = get(key2);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
pool.put12(CLASS, newUTF8(value));
|
pool.put12(type, newUTF8(value));
|
||||||
result = new Item(index++, key2);
|
result = new Item(index++, key2);
|
||||||
put(result);
|
put(result);
|
||||||
}
|
}
|
||||||
@@ -1167,72 +1207,7 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
* @return the index of a new or already existing class reference item.
|
* @return the index of a new or already existing class reference item.
|
||||||
*/
|
*/
|
||||||
public int newClass(final String value) {
|
public int newClass(final String value) {
|
||||||
return newClassItem(value).index;
|
return newStringishItem(CLASS, value).index;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a module name to the constant pool.
|
|
||||||
*
|
|
||||||
* Does nothing if the constant pool already contains a similar item.
|
|
||||||
* <i>This method is intended for {@link Attribute} sub classes, and is
|
|
||||||
* normally not needed by class generators or adapters.</i>
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
* the module name
|
|
||||||
* @return the index of a new or already existing module reference item.
|
|
||||||
*/
|
|
||||||
public int newModule(String value) {
|
|
||||||
key2.set(MODULE, value, null, null);
|
|
||||||
Item result = get(key2);
|
|
||||||
if (result == null) {
|
|
||||||
pool.put12(MODULE, newUTF8(value));
|
|
||||||
result = new Item(index++, key2);
|
|
||||||
put(result);
|
|
||||||
}
|
|
||||||
return result.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a package name to the constant pool.
|
|
||||||
*
|
|
||||||
* Does nothing if the constant pool already contains a similar item.
|
|
||||||
* <i>This method is intended for {@link Attribute} sub classes, and is
|
|
||||||
* normally not needed by class generators or adapters.</i>
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
* the internal name of the package.
|
|
||||||
* @return the index of a new or already existing package reference item.
|
|
||||||
*/
|
|
||||||
public int newPackage(String value) {
|
|
||||||
key2.set(PACKAGE, value, null, null);
|
|
||||||
Item result = get(key2);
|
|
||||||
if (result == null) {
|
|
||||||
pool.put12(PACKAGE, newUTF8(value));
|
|
||||||
result = new Item(index++, key2);
|
|
||||||
put(result);
|
|
||||||
}
|
|
||||||
return result.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a method type reference to the constant pool of the class being
|
|
||||||
* build. Does nothing if the constant pool already contains a similar item.
|
|
||||||
* <i>This method is intended for {@link Attribute} sub classes, and is
|
|
||||||
* normally not needed by class generators or adapters.</i>
|
|
||||||
*
|
|
||||||
* @param methodDesc
|
|
||||||
* method descriptor of the method type.
|
|
||||||
* @return a new or already existing method type reference item.
|
|
||||||
*/
|
|
||||||
Item newMethodTypeItem(final String methodDesc) {
|
|
||||||
key2.set(MTYPE, methodDesc, null, null);
|
|
||||||
Item result = get(key2);
|
|
||||||
if (result == null) {
|
|
||||||
pool.put12(MTYPE, newUTF8(methodDesc));
|
|
||||||
result = new Item(index++, key2);
|
|
||||||
put(result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1247,7 +1222,37 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
* item.
|
* item.
|
||||||
*/
|
*/
|
||||||
public int newMethodType(final String methodDesc) {
|
public int newMethodType(final String methodDesc) {
|
||||||
return newMethodTypeItem(methodDesc).index;
|
return newStringishItem(MTYPE, methodDesc).index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a module reference to the constant pool of the class being
|
||||||
|
* build. Does nothing if the constant pool already contains a similar item.
|
||||||
|
* <i>This method is intended for {@link Attribute} sub classes, and is
|
||||||
|
* normally not needed by class generators or adapters.</i>
|
||||||
|
*
|
||||||
|
* @param moduleName
|
||||||
|
* name of the module.
|
||||||
|
* @return the index of a new or already existing module reference
|
||||||
|
* item.
|
||||||
|
*/
|
||||||
|
public int newModule(final String moduleName) {
|
||||||
|
return newStringishItem(MODULE, moduleName).index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a package reference to the constant pool of the class being
|
||||||
|
* build. Does nothing if the constant pool already contains a similar item.
|
||||||
|
* <i>This method is intended for {@link Attribute} sub classes, and is
|
||||||
|
* normally not needed by class generators or adapters.</i>
|
||||||
|
*
|
||||||
|
* @param packageName
|
||||||
|
* name of the package in its internal form.
|
||||||
|
* @return the index of a new or already existing module reference
|
||||||
|
* item.
|
||||||
|
*/
|
||||||
|
public int newPackage(final String packageName) {
|
||||||
|
return newStringishItem(PACKAGE, packageName).index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1292,38 +1297,6 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a handle to the constant pool of the class being build. Does nothing
|
|
||||||
* if the constant pool already contains a similar item. <i>This method is
|
|
||||||
* intended for {@link Attribute} sub classes, and is normally not needed by
|
|
||||||
* class generators or adapters.</i>
|
|
||||||
*
|
|
||||||
* @param tag
|
|
||||||
* the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
|
|
||||||
* {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
|
|
||||||
* {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
|
|
||||||
* {@link Opcodes#H_INVOKESTATIC},
|
|
||||||
* {@link Opcodes#H_INVOKESPECIAL},
|
|
||||||
* {@link Opcodes#H_NEWINVOKESPECIAL} or
|
|
||||||
* {@link Opcodes#H_INVOKEINTERFACE}.
|
|
||||||
* @param owner
|
|
||||||
* the internal name of the field or method owner class.
|
|
||||||
* @param name
|
|
||||||
* the name of the field or method.
|
|
||||||
* @param desc
|
|
||||||
* the descriptor of the field or method.
|
|
||||||
* @return the index of a new or already existing method type reference
|
|
||||||
* item.
|
|
||||||
*
|
|
||||||
* @deprecated this method is superseded by
|
|
||||||
* {@link #newHandle(int, String, String, String, boolean)}.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public int newHandle(final int tag, final String owner, final String name,
|
|
||||||
final String desc) {
|
|
||||||
return newHandle(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a handle to the constant pool of the class being build. Does nothing
|
* Adds a handle to the constant pool of the class being build. Does nothing
|
||||||
* if the constant pool already contains a similar item. <i>This method is
|
* if the constant pool already contains a similar item. <i>This method is
|
||||||
@@ -1628,25 +1601,6 @@ public class ClassWriter extends ClassVisitor {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a string to the constant pool of the class being build. Does nothing
|
|
||||||
* if the constant pool already contains a similar item.
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
* the String value.
|
|
||||||
* @return a new or already existing string item.
|
|
||||||
*/
|
|
||||||
private Item newString(final String value) {
|
|
||||||
key2.set(STR, value, null, null);
|
|
||||||
Item result = get(key2);
|
|
||||||
if (result == null) {
|
|
||||||
pool.put12(STR, newUTF8(value));
|
|
||||||
result = new Item(index++, key2);
|
|
||||||
put(result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a name and type to the constant pool of the class being build. Does
|
* Adds a name and type to the constant pool of the class being build. Does
|
||||||
* nothing if the constant pool already contains a similar item. <i>This
|
* nothing if the constant pool already contains a similar item. <i>This
|
||||||
|
|||||||
85
src/org/redkale/asm/CurrentFrame.java
Normal file
85
src/org/redkale/asm/CurrentFrame.java
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ASM: a very small and fast Java bytecode manipulation framework
|
||||||
|
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.redkale.asm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about the input stack map frame at the "current" instruction of a
|
||||||
|
* method. This is implemented as a Frame subclass for a "basic block"
|
||||||
|
* containing only one instruction.
|
||||||
|
*
|
||||||
|
* @author Eric Bruneton
|
||||||
|
*/
|
||||||
|
class CurrentFrame extends Frame {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this CurrentFrame to the input stack map frame of the next "current"
|
||||||
|
* instruction, i.e. the instruction just after the given one. It is assumed
|
||||||
|
* that the value of this object when this method is called is the stack map
|
||||||
|
* frame status just before the given instruction is executed.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
void execute(int opcode, int arg, ClassWriter cw, Item item) {
|
||||||
|
super.execute(opcode, arg, cw, item);
|
||||||
|
Frame successor = new Frame();
|
||||||
|
merge(cw, successor, 0);
|
||||||
|
set(successor);
|
||||||
|
owner.inputStackTop = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -69,7 +69,7 @@ public abstract class FieldVisitor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The ASM API version implemented by this visitor. The value of this field
|
* The ASM API version implemented by this visitor. The value of this field
|
||||||
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
protected final int api;
|
protected final int api;
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ public abstract class FieldVisitor {
|
|||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
public FieldVisitor(final int api) {
|
public FieldVisitor(final int api) {
|
||||||
this(api, null);
|
this(api, null);
|
||||||
@@ -95,15 +95,12 @@ public abstract class FieldVisitor {
|
|||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
* @param fv
|
* @param fv
|
||||||
* the field visitor to which this visitor must delegate method
|
* the field visitor to which this visitor must delegate method
|
||||||
* calls. May be null.
|
* calls. May be null.
|
||||||
*/
|
*/
|
||||||
public FieldVisitor(final int api, final FieldVisitor fv) {
|
public FieldVisitor(final int api, final FieldVisitor fv) {
|
||||||
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.fv = fv;
|
this.fv = fv;
|
||||||
}
|
}
|
||||||
@@ -145,9 +142,6 @@ public abstract class FieldVisitor {
|
|||||||
*/
|
*/
|
||||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||||
TypePath typePath, String desc, boolean visible) {
|
TypePath typePath, String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (fv != null) {
|
if (fv != null) {
|
||||||
return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ final class FieldWriter extends FieldVisitor {
|
|||||||
*/
|
*/
|
||||||
FieldWriter(final ClassWriter cw, final int access, final String name,
|
FieldWriter(final ClassWriter cw, final int access, final String name,
|
||||||
final String desc, final String signature, final Object value) {
|
final String desc, final String signature, final Object value) {
|
||||||
super(Opcodes.ASM5);
|
super(Opcodes.ASM6);
|
||||||
if (cw.firstField == null) {
|
if (cw.firstField == null) {
|
||||||
cw.firstField = this;
|
cw.firstField = this;
|
||||||
} else {
|
} else {
|
||||||
@@ -158,7 +158,7 @@ final class FieldWriter extends FieldVisitor {
|
|||||||
this.access = access;
|
this.access = access;
|
||||||
this.name = cw.newUTF8(name);
|
this.name = cw.newUTF8(name);
|
||||||
this.desc = cw.newUTF8(desc);
|
this.desc = cw.newUTF8(desc);
|
||||||
if (ClassReader.SIGNATURES && signature != null) {
|
if (signature != null) {
|
||||||
this.signature = cw.newUTF8(signature);
|
this.signature = cw.newUTF8(signature);
|
||||||
}
|
}
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@@ -173,9 +173,6 @@ final class FieldWriter extends FieldVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public AnnotationVisitor visitAnnotation(final String desc,
|
public AnnotationVisitor visitAnnotation(final String desc,
|
||||||
final boolean visible) {
|
final boolean visible) {
|
||||||
if (!ClassReader.ANNOTATIONS) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ByteVector bv = new ByteVector();
|
ByteVector bv = new ByteVector();
|
||||||
// write type, and reserve space for values count
|
// write type, and reserve space for values count
|
||||||
bv.putShort(cw.newUTF8(desc)).putShort(0);
|
bv.putShort(cw.newUTF8(desc)).putShort(0);
|
||||||
@@ -193,9 +190,6 @@ final class FieldWriter extends FieldVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public AnnotationVisitor visitTypeAnnotation(final int typeRef,
|
public AnnotationVisitor visitTypeAnnotation(final int typeRef,
|
||||||
final TypePath typePath, final String desc, final boolean visible) {
|
final TypePath typePath, final String desc, final boolean visible) {
|
||||||
if (!ClassReader.ANNOTATIONS) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ByteVector bv = new ByteVector();
|
ByteVector bv = new ByteVector();
|
||||||
// write target_type and target_info
|
// write target_type and target_info
|
||||||
AnnotationWriter.putTarget(typeRef, typePath, bv);
|
AnnotationWriter.putTarget(typeRef, typePath, bv);
|
||||||
@@ -249,23 +243,23 @@ final class FieldWriter extends FieldVisitor {
|
|||||||
cw.newUTF8("Deprecated");
|
cw.newUTF8("Deprecated");
|
||||||
size += 6;
|
size += 6;
|
||||||
}
|
}
|
||||||
if (ClassReader.SIGNATURES && signature != 0) {
|
if (signature != 0) {
|
||||||
cw.newUTF8("Signature");
|
cw.newUTF8("Signature");
|
||||||
size += 8;
|
size += 8;
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && anns != null) {
|
if (anns != null) {
|
||||||
cw.newUTF8("RuntimeVisibleAnnotations");
|
cw.newUTF8("RuntimeVisibleAnnotations");
|
||||||
size += 8 + anns.getSize();
|
size += 8 + anns.getSize();
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && ianns != null) {
|
if (ianns != null) {
|
||||||
cw.newUTF8("RuntimeInvisibleAnnotations");
|
cw.newUTF8("RuntimeInvisibleAnnotations");
|
||||||
size += 8 + ianns.getSize();
|
size += 8 + ianns.getSize();
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && tanns != null) {
|
if (tanns != null) {
|
||||||
cw.newUTF8("RuntimeVisibleTypeAnnotations");
|
cw.newUTF8("RuntimeVisibleTypeAnnotations");
|
||||||
size += 8 + tanns.getSize();
|
size += 8 + tanns.getSize();
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && itanns != null) {
|
if (itanns != null) {
|
||||||
cw.newUTF8("RuntimeInvisibleTypeAnnotations");
|
cw.newUTF8("RuntimeInvisibleTypeAnnotations");
|
||||||
size += 8 + itanns.getSize();
|
size += 8 + itanns.getSize();
|
||||||
}
|
}
|
||||||
@@ -299,19 +293,19 @@ final class FieldWriter extends FieldVisitor {
|
|||||||
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
|
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
|
||||||
++attributeCount;
|
++attributeCount;
|
||||||
}
|
}
|
||||||
if (ClassReader.SIGNATURES && signature != 0) {
|
if (signature != 0) {
|
||||||
++attributeCount;
|
++attributeCount;
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && anns != null) {
|
if (anns != null) {
|
||||||
++attributeCount;
|
++attributeCount;
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && ianns != null) {
|
if (ianns != null) {
|
||||||
++attributeCount;
|
++attributeCount;
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && tanns != null) {
|
if (tanns != null) {
|
||||||
++attributeCount;
|
++attributeCount;
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && itanns != null) {
|
if (itanns != null) {
|
||||||
++attributeCount;
|
++attributeCount;
|
||||||
}
|
}
|
||||||
if (attrs != null) {
|
if (attrs != null) {
|
||||||
@@ -331,23 +325,23 @@ final class FieldWriter extends FieldVisitor {
|
|||||||
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
|
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
|
||||||
out.putShort(cw.newUTF8("Deprecated")).putInt(0);
|
out.putShort(cw.newUTF8("Deprecated")).putInt(0);
|
||||||
}
|
}
|
||||||
if (ClassReader.SIGNATURES && signature != 0) {
|
if (signature != 0) {
|
||||||
out.putShort(cw.newUTF8("Signature"));
|
out.putShort(cw.newUTF8("Signature"));
|
||||||
out.putInt(2).putShort(signature);
|
out.putInt(2).putShort(signature);
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && anns != null) {
|
if (anns != null) {
|
||||||
out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
|
out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
|
||||||
anns.put(out);
|
anns.put(out);
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && ianns != null) {
|
if (ianns != null) {
|
||||||
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
|
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
|
||||||
ianns.put(out);
|
ianns.put(out);
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && tanns != null) {
|
if (tanns != null) {
|
||||||
out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
|
out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
|
||||||
tanns.put(out);
|
tanns.put(out);
|
||||||
}
|
}
|
||||||
if (ClassReader.ANNOTATIONS && itanns != null) {
|
if (itanns != null) {
|
||||||
out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
|
out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
|
||||||
itanns.put(out);
|
itanns.put(out);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ package org.redkale.asm;
|
|||||||
*
|
*
|
||||||
* @author Eric Bruneton
|
* @author Eric Bruneton
|
||||||
*/
|
*/
|
||||||
final class Frame {
|
class Frame {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Frames are computed in a two steps process: during the visit of each
|
* Frames are computed in a two steps process: during the visit of each
|
||||||
@@ -192,7 +192,7 @@ final class Frame {
|
|||||||
private static final int LOCAL = 0x2000000;
|
private static final int LOCAL = 0x2000000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kind of the the types that are relative to the stack of an input stack
|
* Kind of the types that are relative to the stack of an input stack
|
||||||
* map frame. The value of such types is a position relatively to the top of
|
* map frame. The value of such types is a position relatively to the top of
|
||||||
* this stack.
|
* this stack.
|
||||||
*/
|
*/
|
||||||
@@ -525,7 +525,7 @@ final class Frame {
|
|||||||
* When the stack map frames are completely computed, this field is the
|
* When the stack map frames are completely computed, this field is the
|
||||||
* actual number of types in {@link #outputStack}.
|
* actual number of types in {@link #outputStack}.
|
||||||
*/
|
*/
|
||||||
private int outputStackTop;
|
int outputStackTop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of types that are initialized in the basic block.
|
* Number of types that are initialized in the basic block.
|
||||||
@@ -549,6 +549,110 @@ final class Frame {
|
|||||||
*/
|
*/
|
||||||
private int[] initializations;
|
private int[] initializations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this frame to the given value.
|
||||||
|
*
|
||||||
|
* @param cw
|
||||||
|
* the ClassWriter to which this label belongs.
|
||||||
|
* @param nLocal
|
||||||
|
* the number of local variables.
|
||||||
|
* @param local
|
||||||
|
* the local variable types. Primitive types are represented by
|
||||||
|
* {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
|
||||||
|
* {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
|
||||||
|
* {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
|
||||||
|
* {@link Opcodes#UNINITIALIZED_THIS} (long and double are
|
||||||
|
* represented by a single element). Reference types are
|
||||||
|
* represented by String objects (representing internal names),
|
||||||
|
* and uninitialized types by Label objects (this label
|
||||||
|
* designates the NEW instruction that created this uninitialized
|
||||||
|
* value).
|
||||||
|
* @param nStack
|
||||||
|
* the number of operand stack elements.
|
||||||
|
* @param stack
|
||||||
|
* the operand stack types (same format as the "local" array).
|
||||||
|
*/
|
||||||
|
final void set(ClassWriter cw, final int nLocal, final Object[] local,
|
||||||
|
final int nStack, final Object[] stack) {
|
||||||
|
int i = convert(cw, nLocal, local, inputLocals);
|
||||||
|
while (i < local.length) {
|
||||||
|
inputLocals[i++] = TOP;
|
||||||
|
}
|
||||||
|
int nStackTop = 0;
|
||||||
|
for (int j = 0; j < nStack; ++j) {
|
||||||
|
if (stack[j] == Opcodes.LONG || stack[j] == Opcodes.DOUBLE) {
|
||||||
|
++nStackTop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputStack = new int[nStack + nStackTop];
|
||||||
|
convert(cw, nStack, stack, inputStack);
|
||||||
|
outputStackTop = 0;
|
||||||
|
initializationCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts types from the MethodWriter.visitFrame() format to the Frame
|
||||||
|
* format.
|
||||||
|
*
|
||||||
|
* @param cw
|
||||||
|
* the ClassWriter to which this label belongs.
|
||||||
|
* @param nInput
|
||||||
|
* the number of types to convert.
|
||||||
|
* @param input
|
||||||
|
* the types to convert. Primitive types are represented by
|
||||||
|
* {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
|
||||||
|
* {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
|
||||||
|
* {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
|
||||||
|
* {@link Opcodes#UNINITIALIZED_THIS} (long and double are
|
||||||
|
* represented by a single element). Reference types are
|
||||||
|
* represented by String objects (representing internal names),
|
||||||
|
* and uninitialized types by Label objects (this label
|
||||||
|
* designates the NEW instruction that created this uninitialized
|
||||||
|
* value).
|
||||||
|
* @param output
|
||||||
|
* where to store the converted types.
|
||||||
|
* @return the number of output elements.
|
||||||
|
*/
|
||||||
|
private static int convert(ClassWriter cw, int nInput, Object[] input,
|
||||||
|
int[] output) {
|
||||||
|
int i = 0;
|
||||||
|
for (int j = 0; j < nInput; ++j) {
|
||||||
|
if (input[j] instanceof Integer) {
|
||||||
|
output[i++] = BASE | ((Integer) input[j]).intValue();
|
||||||
|
if (input[j] == Opcodes.LONG || input[j] == Opcodes.DOUBLE) {
|
||||||
|
output[i++] = TOP;
|
||||||
|
}
|
||||||
|
} else if (input[j] instanceof String) {
|
||||||
|
output[i++] = type(cw, Type.getObjectType((String) input[j])
|
||||||
|
.getDescriptor());
|
||||||
|
} else {
|
||||||
|
output[i++] = UNINITIALIZED
|
||||||
|
| cw.addUninitializedType("",
|
||||||
|
((Label) input[j]).position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this frame to the value of the given frame. WARNING: after this
|
||||||
|
* method is called the two frames share the same data structures. It is
|
||||||
|
* recommended to discard the given frame f to avoid unexpected side
|
||||||
|
* effects.
|
||||||
|
*
|
||||||
|
* @param f
|
||||||
|
* The new frame value.
|
||||||
|
*/
|
||||||
|
final void set(final Frame f) {
|
||||||
|
inputLocals = f.inputLocals;
|
||||||
|
inputStack = f.inputStack;
|
||||||
|
outputLocals = f.outputLocals;
|
||||||
|
outputStack = f.outputStack;
|
||||||
|
outputStackTop = f.outputStackTop;
|
||||||
|
initializationCount = f.initializationCount;
|
||||||
|
initializations = f.initializations;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the output frame local variable type at the given index.
|
* Returns the output frame local variable type at the given index.
|
||||||
*
|
*
|
||||||
@@ -614,7 +718,7 @@ final class Frame {
|
|||||||
}
|
}
|
||||||
// pushes the type on the output stack
|
// pushes the type on the output stack
|
||||||
outputStack[outputStackTop++] = type;
|
outputStack[outputStackTop++] = type;
|
||||||
// updates the maximun height reached by the output stack, if needed
|
// updates the maximum height reached by the output stack, if needed
|
||||||
int top = owner.inputStackTop + outputStackTop;
|
int top = owner.inputStackTop + outputStackTop;
|
||||||
if (top > owner.outputStackMax) {
|
if (top > owner.outputStackMax) {
|
||||||
owner.outputStackMax = top;
|
owner.outputStackMax = top;
|
||||||
@@ -650,7 +754,7 @@ final class Frame {
|
|||||||
* a type descriptor.
|
* a type descriptor.
|
||||||
* @return the int encoding of the given type.
|
* @return the int encoding of the given type.
|
||||||
*/
|
*/
|
||||||
private static int type(final ClassWriter cw, final String desc) {
|
static int type(final ClassWriter cw, final String desc) {
|
||||||
String t;
|
String t;
|
||||||
int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
|
int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
|
||||||
switch (desc.charAt(index)) {
|
switch (desc.charAt(index)) {
|
||||||
@@ -838,7 +942,7 @@ final class Frame {
|
|||||||
* @param maxLocals
|
* @param maxLocals
|
||||||
* the maximum number of local variables of this method.
|
* the maximum number of local variables of this method.
|
||||||
*/
|
*/
|
||||||
void initInputFrame(final ClassWriter cw, final int access,
|
final void initInputFrame(final ClassWriter cw, final int access,
|
||||||
final Type[] args, final int maxLocals) {
|
final Type[] args, final int maxLocals) {
|
||||||
inputLocals = new int[maxLocals];
|
inputLocals = new int[maxLocals];
|
||||||
inputStack = new int[0];
|
inputStack = new int[0];
|
||||||
@@ -981,7 +1085,7 @@ final class Frame {
|
|||||||
case Opcodes.AALOAD:
|
case Opcodes.AALOAD:
|
||||||
pop(1);
|
pop(1);
|
||||||
t1 = pop();
|
t1 = pop();
|
||||||
push(ELEMENT_OF + t1);
|
push(t1 == NULL ? t1 : ELEMENT_OF + t1);
|
||||||
break;
|
break;
|
||||||
case Opcodes.ISTORE:
|
case Opcodes.ISTORE:
|
||||||
case Opcodes.FSTORE:
|
case Opcodes.FSTORE:
|
||||||
@@ -1312,7 +1416,7 @@ final class Frame {
|
|||||||
* @return <tt>true</tt> if the input frame of the given label has been
|
* @return <tt>true</tt> if the input frame of the given label has been
|
||||||
* changed by this operation.
|
* changed by this operation.
|
||||||
*/
|
*/
|
||||||
boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
|
final boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
int i, s, dim, kind, t;
|
int i, s, dim, kind, t;
|
||||||
|
|
||||||
|
|||||||
@@ -99,34 +99,6 @@ public final class Handle {
|
|||||||
*/
|
*/
|
||||||
final boolean itf;
|
final boolean itf;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new field or method handle.
|
|
||||||
*
|
|
||||||
* @param tag
|
|
||||||
* the kind of field or method designated by this Handle. Must be
|
|
||||||
* {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
|
|
||||||
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
|
|
||||||
* {@link Opcodes#H_INVOKEVIRTUAL},
|
|
||||||
* {@link Opcodes#H_INVOKESTATIC},
|
|
||||||
* {@link Opcodes#H_INVOKESPECIAL},
|
|
||||||
* {@link Opcodes#H_NEWINVOKESPECIAL} or
|
|
||||||
* {@link Opcodes#H_INVOKEINTERFACE}.
|
|
||||||
* @param owner
|
|
||||||
* the internal name of the class that owns the field or method
|
|
||||||
* designated by this handle.
|
|
||||||
* @param name
|
|
||||||
* the name of the field or method designated by this handle.
|
|
||||||
* @param desc
|
|
||||||
* the descriptor of the field or method designated by this
|
|
||||||
* handle.
|
|
||||||
*
|
|
||||||
* @deprecated this constructor has been superseded
|
|
||||||
* by {@link #Handle(int, String, String, String, boolean)}.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public Handle(int tag, String owner, String name, String desc) {
|
|
||||||
this(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new field or method handle.
|
* Constructs a new field or method handle.
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ final class Item {
|
|||||||
* {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
|
* {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
|
||||||
* {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
|
* {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
|
||||||
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
|
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
|
||||||
|
* {@link ClassWriter#MODULE}, {@link ClassWriter#PACKAGE},
|
||||||
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
|
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
|
||||||
*
|
*
|
||||||
* MethodHandle constant 9 variations are stored using a range of 9 values
|
* MethodHandle constant 9 variations are stored using a range of 9 values
|
||||||
@@ -239,12 +240,12 @@ final class Item {
|
|||||||
this.strVal3 = strVal3;
|
this.strVal3 = strVal3;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ClassWriter.CLASS:
|
case ClassWriter.CLASS:
|
||||||
case ClassWriter.MODULE:
|
|
||||||
case ClassWriter.PACKAGE:
|
|
||||||
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
|
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
|
||||||
case ClassWriter.UTF8:
|
case ClassWriter.UTF8:
|
||||||
case ClassWriter.STR:
|
case ClassWriter.STR:
|
||||||
case ClassWriter.MTYPE:
|
case ClassWriter.MTYPE:
|
||||||
|
case ClassWriter.MODULE:
|
||||||
|
case ClassWriter.PACKAGE:
|
||||||
case ClassWriter.TYPE_NORMAL:
|
case ClassWriter.TYPE_NORMAL:
|
||||||
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
|
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -139,7 +139,8 @@ public class Label {
|
|||||||
/**
|
/**
|
||||||
* Field used to associate user information to a label. Warning: this field
|
* Field used to associate user information to a label. Warning: this field
|
||||||
* is used by the ASM tree package. In order to use it with the ASM tree
|
* is used by the ASM tree package. In order to use it with the ASM tree
|
||||||
* package you must override the method.
|
* package you must override the
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public Object info;
|
public Object info;
|
||||||
|
|
||||||
@@ -388,13 +389,12 @@ public class Label {
|
|||||||
* the position of this label in the bytecode.
|
* the position of this label in the bytecode.
|
||||||
* @param data
|
* @param data
|
||||||
* the bytecode of the method.
|
* the bytecode of the method.
|
||||||
* @return <tt>true</tt> if a blank that was left for this label was to
|
* @return <tt>true</tt> if a blank that was left for this label was too
|
||||||
* small to store the offset. In such a case the corresponding jump
|
* small to store the offset. In such a case the corresponding jump
|
||||||
* instruction is replaced with a pseudo instruction (using unused
|
* instruction is replaced with a pseudo instruction (using unused
|
||||||
* opcodes) using an unsigned two bytes offset. These pseudo
|
* opcodes) using an unsigned two bytes offset. These pseudo
|
||||||
* instructions will need to be replaced with true instructions with
|
* instructions will be replaced with standard bytecode instructions
|
||||||
* wider offsets (4 bytes instead of 2). This is done in
|
* with wider offsets (4 bytes instead of 2), in ClassReader.
|
||||||
* {@link MethodWriter#resizeInstructions}.
|
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if this label has already been resolved, or if it has not
|
* if this label has already been resolved, or if it has not
|
||||||
* been created by the given code writer.
|
* been created by the given code writer.
|
||||||
@@ -453,7 +453,7 @@ public class Label {
|
|||||||
* @return the first label of the series to which this label belongs.
|
* @return the first label of the series to which this label belongs.
|
||||||
*/
|
*/
|
||||||
Label getFirst() {
|
Label getFirst() {
|
||||||
return !ClassReader.FRAMES || frame == null ? this : frame.owner;
|
return frame == null ? this : frame.owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class MethodDebugVisitor {
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<Label, Integer> labels = new LinkedHashMap();
|
private final Map<Label, Integer> labels = new LinkedHashMap<>();
|
||||||
|
|
||||||
private static final String[] opcodes = new String[200]; //0 -18
|
private static final String[] opcodes = new String[200]; //0 -18
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ public abstract class MethodVisitor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The ASM API version implemented by this visitor. The value of this field
|
* The ASM API version implemented by this visitor. The value of this field
|
||||||
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
protected final int api;
|
protected final int api;
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ public abstract class MethodVisitor {
|
|||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
public MethodVisitor(final int api) {
|
public MethodVisitor(final int api) {
|
||||||
this(api, null);
|
this(api, null);
|
||||||
@@ -112,15 +112,12 @@ public abstract class MethodVisitor {
|
|||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
* @param mv
|
* @param mv
|
||||||
* the method visitor to which this visitor must delegate method
|
* the method visitor to which this visitor must delegate method
|
||||||
* calls. May be null.
|
* calls. May be null.
|
||||||
*/
|
*/
|
||||||
public MethodVisitor(final int api, final MethodVisitor mv) {
|
public MethodVisitor(final int api, final MethodVisitor mv) {
|
||||||
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.mv = mv;
|
this.mv = mv;
|
||||||
}
|
}
|
||||||
@@ -140,9 +137,6 @@ public abstract class MethodVisitor {
|
|||||||
* allowed (see {@link Opcodes}).
|
* allowed (see {@link Opcodes}).
|
||||||
*/
|
*/
|
||||||
public void visitParameter(String name, int access) {
|
public void visitParameter(String name, int access) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
mv.visitParameter(name, access);
|
mv.visitParameter(name, access);
|
||||||
}
|
}
|
||||||
@@ -209,9 +203,6 @@ public abstract class MethodVisitor {
|
|||||||
*/
|
*/
|
||||||
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
public AnnotationVisitor visitTypeAnnotation(int typeRef,
|
||||||
TypePath typePath, String desc, boolean visible) {
|
TypePath typePath, String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
return mv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
return mv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||||
}
|
}
|
||||||
@@ -453,34 +444,6 @@ public abstract class MethodVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Visits a method instruction. A method instruction is an instruction that
|
|
||||||
* invokes a method.
|
|
||||||
*
|
|
||||||
* @param opcode
|
|
||||||
* the opcode of the type instruction to be visited. This opcode
|
|
||||||
* is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
|
|
||||||
* INVOKEINTERFACE.
|
|
||||||
* @param owner
|
|
||||||
* the internal name of the method's owner class (see
|
|
||||||
* {@link Type#getInternalName() getInternalName}).
|
|
||||||
* @param name
|
|
||||||
* the method's name.
|
|
||||||
* @param desc
|
|
||||||
* the method's descriptor (see {@link Type Type}).
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void visitMethodInsn(int opcode, String owner, String name,
|
|
||||||
String desc) {
|
|
||||||
if (api >= Opcodes.ASM5) {
|
|
||||||
boolean itf = opcode == Opcodes.INVOKEINTERFACE;
|
|
||||||
visitMethodInsn(opcode, owner, name, desc, itf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
|
||||||
mv.visitMethodInsn(opcode, owner, name, desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visits a method instruction. A method instruction is an instruction that
|
* Visits a method instruction. A method instruction is an instruction that
|
||||||
@@ -502,14 +465,6 @@ public abstract class MethodVisitor {
|
|||||||
*/
|
*/
|
||||||
public void visitMethodInsn(int opcode, String owner, String name,
|
public void visitMethodInsn(int opcode, String owner, String name,
|
||||||
String desc, boolean itf) {
|
String desc, boolean itf) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"INVOKESPECIAL/STATIC on interfaces require ASM 5");
|
|
||||||
}
|
|
||||||
visitMethodInsn(opcode, owner, name, desc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
mv.visitMethodInsn(opcode, owner, name, desc, itf);
|
mv.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||||
}
|
}
|
||||||
@@ -723,9 +678,6 @@ public abstract class MethodVisitor {
|
|||||||
*/
|
*/
|
||||||
public AnnotationVisitor visitInsnAnnotation(int typeRef,
|
public AnnotationVisitor visitInsnAnnotation(int typeRef,
|
||||||
TypePath typePath, String desc, boolean visible) {
|
TypePath typePath, String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
|
return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
|
||||||
}
|
}
|
||||||
@@ -783,9 +735,6 @@ public abstract class MethodVisitor {
|
|||||||
*/
|
*/
|
||||||
public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
|
public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
|
||||||
TypePath typePath, String desc, boolean visible) {
|
TypePath typePath, String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
|
return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
|
||||||
}
|
}
|
||||||
@@ -854,9 +803,6 @@ public abstract class MethodVisitor {
|
|||||||
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
|
public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
|
||||||
TypePath typePath, Label[] start, Label[] end, int[] index,
|
TypePath typePath, Label[] start, Label[] end, int[] index,
|
||||||
String desc, boolean visible) {
|
String desc, boolean visible) {
|
||||||
if (api < Opcodes.ASM5) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
if (mv != null) {
|
if (mv != null) {
|
||||||
return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
|
return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
|
||||||
end, index, desc, visible);
|
end, index, desc, visible);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
219
src/org/redkale/asm/ModuleVisitor.java
Normal file
219
src/org/redkale/asm/ModuleVisitor.java
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ASM: a very small and fast Java bytecode manipulation framework
|
||||||
|
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package org.redkale.asm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A visitor to visit a Java module. The methods of this class must be called in
|
||||||
|
* the following order: <tt>visitMainClass</tt> | ( <tt>visitPackage</tt> |
|
||||||
|
* <tt>visitRequire</tt> | <tt>visitExport</tt> | <tt>visitOpen</tt> |
|
||||||
|
* <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>.
|
||||||
|
*
|
||||||
|
* The methods {@link #visitRequire(String, int, String)}, {@link #visitExport(String, int, String...)},
|
||||||
|
* {@link #visitOpen(String, int, String...)} and {@link #visitPackage(String)}
|
||||||
|
* take as parameter a package name or a module name. Unlike the other names which are internal names
|
||||||
|
* (names separated by slash), module and package names are qualified names (names separated by dot).
|
||||||
|
*
|
||||||
|
* @author Remi Forax
|
||||||
|
*/
|
||||||
|
public abstract class ModuleVisitor {
|
||||||
|
/**
|
||||||
|
* The ASM API version implemented by this visitor. The value of this field
|
||||||
|
* must be {@link Opcodes#ASM6}.
|
||||||
|
*/
|
||||||
|
protected final int api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The module visitor to which this visitor must delegate method calls. May
|
||||||
|
* be null.
|
||||||
|
*/
|
||||||
|
protected ModuleVisitor mv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new {@link ModuleVisitor}.
|
||||||
|
*
|
||||||
|
* @param api
|
||||||
|
* the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
|
||||||
|
*/
|
||||||
|
public ModuleVisitor(final int api) {
|
||||||
|
this(api, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new {@link ModuleVisitor}.
|
||||||
|
*
|
||||||
|
* @param api
|
||||||
|
* the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
|
||||||
|
* @param mv
|
||||||
|
* the module visitor to which this visitor must delegate method
|
||||||
|
* calls. May be null.
|
||||||
|
*/
|
||||||
|
public ModuleVisitor(final int api, final ModuleVisitor mv) {
|
||||||
|
if (api != Opcodes.ASM6) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
this.api = api;
|
||||||
|
this.mv = mv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the main class of the current module.
|
||||||
|
*
|
||||||
|
* @param mainClass the internal name of the main class of the current module.
|
||||||
|
*/
|
||||||
|
public void visitMainClass(String mainClass) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitMainClass(mainClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit a package of the current module.
|
||||||
|
*
|
||||||
|
* @param packaze the qualified name of a package.
|
||||||
|
*/
|
||||||
|
public void visitPackage(String packaze) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitPackage(packaze);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits a dependence of the current module.
|
||||||
|
*
|
||||||
|
* @param module the qualified name of the dependence.
|
||||||
|
* @param access the access flag of the dependence among
|
||||||
|
* ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC
|
||||||
|
* and ACC_MANDATED.
|
||||||
|
* @param version the module version at compile time or null.
|
||||||
|
*/
|
||||||
|
public void visitRequire(String module, int access, String version) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitRequire(module, access, version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit an exported package of the current module.
|
||||||
|
*
|
||||||
|
* @param packaze the qualified name of the exported package.
|
||||||
|
* @param access the access flag of the exported package,
|
||||||
|
* valid values are among {@code ACC_SYNTHETIC} and
|
||||||
|
* {@code ACC_MANDATED}.
|
||||||
|
* @param modules the qualified names of the modules that can access to
|
||||||
|
* the public classes of the exported package or
|
||||||
|
* <tt>null</tt>.
|
||||||
|
*/
|
||||||
|
public void visitExport(String packaze, int access, String... modules) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitExport(packaze, access, modules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit an open package of the current module.
|
||||||
|
*
|
||||||
|
* @param packaze the qualified name of the opened package.
|
||||||
|
* @param access the access flag of the opened package,
|
||||||
|
* valid values are among {@code ACC_SYNTHETIC} and
|
||||||
|
* {@code ACC_MANDATED}.
|
||||||
|
* @param modules the qualified names of the modules that can use deep
|
||||||
|
* reflection to the classes of the open package or
|
||||||
|
* <tt>null</tt>.
|
||||||
|
*/
|
||||||
|
public void visitOpen(String packaze, int access, String... modules) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitOpen(packaze, access, modules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit a service used by the current module.
|
||||||
|
* The name must be the internal name of an interface or a class.
|
||||||
|
*
|
||||||
|
* @param service the internal name of the service.
|
||||||
|
*/
|
||||||
|
public void visitUse(String service) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitUse(service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit an implementation of a service.
|
||||||
|
*
|
||||||
|
* @param service the internal name of the service
|
||||||
|
* @param providers the internal names of the implementations
|
||||||
|
* of the service (there is at least one provider).
|
||||||
|
*/
|
||||||
|
public void visitProvide(String service, String... providers) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitProvide(service, providers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits the end of the module. This method, which is the last one to be
|
||||||
|
* called, is used to inform the visitor that everything have been visited.
|
||||||
|
*/
|
||||||
|
public void visitEnd() {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
322
src/org/redkale/asm/ModuleWriter.java
Normal file
322
src/org/redkale/asm/ModuleWriter.java
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
/*
|
||||||
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ASM: a very small and fast Java bytecode manipulation framework
|
||||||
|
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.redkale.asm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Remi Forax
|
||||||
|
*/
|
||||||
|
final class ModuleWriter extends ModuleVisitor {
|
||||||
|
/**
|
||||||
|
* The class writer to which this Module attribute must be added.
|
||||||
|
*/
|
||||||
|
private final ClassWriter cw;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* size in byte of the Module attribute.
|
||||||
|
*/
|
||||||
|
int size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of attributes associated with the current module
|
||||||
|
* (Version, ConcealPackages, etc)
|
||||||
|
*/
|
||||||
|
int attributeCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size in bytes of the attributes associated with the current module
|
||||||
|
*/
|
||||||
|
int attributesSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* module name index in the constant pool
|
||||||
|
*/
|
||||||
|
private final int name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* module access flags
|
||||||
|
*/
|
||||||
|
private final int access;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* module version index in the constant pool or 0
|
||||||
|
*/
|
||||||
|
private final int version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* module main class index in the constant pool or 0
|
||||||
|
*/
|
||||||
|
private int mainClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of packages
|
||||||
|
*/
|
||||||
|
private int packageCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The packages in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in packageCount
|
||||||
|
*/
|
||||||
|
private ByteVector packages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of requires items
|
||||||
|
*/
|
||||||
|
private int requireCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The requires items in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in requireCount
|
||||||
|
*/
|
||||||
|
private ByteVector requires;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of exports items
|
||||||
|
*/
|
||||||
|
private int exportCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The exports items in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in exportCount
|
||||||
|
*/
|
||||||
|
private ByteVector exports;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of opens items
|
||||||
|
*/
|
||||||
|
private int openCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The opens items in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in openCount
|
||||||
|
*/
|
||||||
|
private ByteVector opens;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of uses items
|
||||||
|
*/
|
||||||
|
private int useCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The uses items in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in useCount
|
||||||
|
*/
|
||||||
|
private ByteVector uses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of provides items
|
||||||
|
*/
|
||||||
|
private int provideCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The uses provides in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in provideCount
|
||||||
|
*/
|
||||||
|
private ByteVector provides;
|
||||||
|
|
||||||
|
ModuleWriter(final ClassWriter cw, final int name,
|
||||||
|
final int access, final int version) {
|
||||||
|
super(Opcodes.ASM6);
|
||||||
|
this.cw = cw;
|
||||||
|
this.size = 16; // name + access + version + 5 counts
|
||||||
|
this.name = name;
|
||||||
|
this.access = access;
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMainClass(String mainClass) {
|
||||||
|
if (this.mainClass == 0) { // protect against several calls to visitMainClass
|
||||||
|
cw.newUTF8("ModuleMainClass");
|
||||||
|
attributeCount++;
|
||||||
|
attributesSize += 8;
|
||||||
|
}
|
||||||
|
this.mainClass = cw.newClass(mainClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitPackage(String packaze) {
|
||||||
|
if (packages == null) {
|
||||||
|
// protect against several calls to visitPackage
|
||||||
|
cw.newUTF8("ModulePackages");
|
||||||
|
packages = new ByteVector();
|
||||||
|
attributeCount++;
|
||||||
|
attributesSize += 8;
|
||||||
|
}
|
||||||
|
packages.putShort(cw.newPackage(packaze));
|
||||||
|
packageCount++;
|
||||||
|
attributesSize += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitRequire(String module, int access, String version) {
|
||||||
|
if (requires == null) {
|
||||||
|
requires = new ByteVector();
|
||||||
|
}
|
||||||
|
requires.putShort(cw.newModule(module))
|
||||||
|
.putShort(access)
|
||||||
|
.putShort(version == null? 0: cw.newUTF8(version));
|
||||||
|
requireCount++;
|
||||||
|
size += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitExport(String packaze, int access, String... modules) {
|
||||||
|
if (exports == null) {
|
||||||
|
exports = new ByteVector();
|
||||||
|
}
|
||||||
|
exports.putShort(cw.newPackage(packaze)).putShort(access);
|
||||||
|
if (modules == null) {
|
||||||
|
exports.putShort(0);
|
||||||
|
size += 6;
|
||||||
|
} else {
|
||||||
|
exports.putShort(modules.length);
|
||||||
|
for(String module: modules) {
|
||||||
|
exports.putShort(cw.newModule(module));
|
||||||
|
}
|
||||||
|
size += 6 + 2 * modules.length;
|
||||||
|
}
|
||||||
|
exportCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitOpen(String packaze, int access, String... modules) {
|
||||||
|
if (opens == null) {
|
||||||
|
opens = new ByteVector();
|
||||||
|
}
|
||||||
|
opens.putShort(cw.newPackage(packaze)).putShort(access);
|
||||||
|
if (modules == null) {
|
||||||
|
opens.putShort(0);
|
||||||
|
size += 6;
|
||||||
|
} else {
|
||||||
|
opens.putShort(modules.length);
|
||||||
|
for(String module: modules) {
|
||||||
|
opens.putShort(cw.newModule(module));
|
||||||
|
}
|
||||||
|
size += 6 + 2 * modules.length;
|
||||||
|
}
|
||||||
|
openCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitUse(String service) {
|
||||||
|
if (uses == null) {
|
||||||
|
uses = new ByteVector();
|
||||||
|
}
|
||||||
|
uses.putShort(cw.newClass(service));
|
||||||
|
useCount++;
|
||||||
|
size += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitProvide(String service, String... providers) {
|
||||||
|
if (provides == null) {
|
||||||
|
provides = new ByteVector();
|
||||||
|
}
|
||||||
|
provides.putShort(cw.newClass(service));
|
||||||
|
provides.putShort(providers.length);
|
||||||
|
for(String provider: providers) {
|
||||||
|
provides.putShort(cw.newClass(provider));
|
||||||
|
}
|
||||||
|
provideCount++;
|
||||||
|
size += 4 + 2 * providers.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitEnd() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
void putAttributes(ByteVector out) {
|
||||||
|
if (mainClass != 0) {
|
||||||
|
out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass);
|
||||||
|
}
|
||||||
|
if (packages != null) {
|
||||||
|
out.putShort(cw.newUTF8("ModulePackages"))
|
||||||
|
.putInt(2 + 2 * packageCount)
|
||||||
|
.putShort(packageCount)
|
||||||
|
.putByteArray(packages.data, 0, packages.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void put(ByteVector out) {
|
||||||
|
out.putInt(size);
|
||||||
|
out.putShort(name).putShort(access).putShort(version);
|
||||||
|
out.putShort(requireCount);
|
||||||
|
if (requires != null) {
|
||||||
|
out.putByteArray(requires.data, 0, requires.length);
|
||||||
|
}
|
||||||
|
out.putShort(exportCount);
|
||||||
|
if (exports != null) {
|
||||||
|
out.putByteArray(exports.data, 0, exports.length);
|
||||||
|
}
|
||||||
|
out.putShort(openCount);
|
||||||
|
if (opens != null) {
|
||||||
|
out.putByteArray(opens.data, 0, opens.length);
|
||||||
|
}
|
||||||
|
out.putShort(useCount);
|
||||||
|
if (uses != null) {
|
||||||
|
out.putByteArray(uses.data, 0, uses.length);
|
||||||
|
}
|
||||||
|
out.putShort(provideCount);
|
||||||
|
if (provides != null) {
|
||||||
|
out.putByteArray(provides.data, 0, provides.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
* ASM: a very small and fast Java bytecode manipulation framework
|
* ASM: a very small and fast Java bytecode manipulation framework
|
||||||
* Copyright (c) 2000-2011 INRIA, France Telecom
|
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@@ -41,25 +70,22 @@ package org.redkale.asm;
|
|||||||
* @author Eric Bruneton
|
* @author Eric Bruneton
|
||||||
* @author Eugene Kuleshov
|
* @author Eugene Kuleshov
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation") // for Integer(int) constructor
|
|
||||||
public interface Opcodes {
|
public interface Opcodes {
|
||||||
|
|
||||||
// ASM API versions
|
// ASM API versions
|
||||||
|
|
||||||
int ASM4 = 4 << 16 | 0 << 8 | 0;
|
int ASM4 = 4 << 16 | 0 << 8 | 0;
|
||||||
int ASM5 = 5 << 16 | 0 << 8 | 0;
|
int ASM5 = 5 << 16 | 0 << 8 | 0;
|
||||||
|
int ASM6 = 6 << 16 | 0 << 8 | 0;
|
||||||
|
|
||||||
// versions
|
// versions
|
||||||
|
|
||||||
int V1_1 = 3 << 16 | 45;
|
|
||||||
int V1_2 = 0 << 16 | 46;
|
|
||||||
int V1_3 = 0 << 16 | 47;
|
|
||||||
int V1_4 = 0 << 16 | 48;
|
|
||||||
int V1_5 = 0 << 16 | 49;
|
int V1_5 = 0 << 16 | 49;
|
||||||
int V1_6 = 0 << 16 | 50;
|
int V1_6 = 0 << 16 | 50;
|
||||||
int V1_7 = 0 << 16 | 51;
|
int V1_7 = 0 << 16 | 51;
|
||||||
int V1_8 = 0 << 16 | 52;
|
int V1_8 = 0 << 16 | 52;
|
||||||
int V1_9 = 0 << 16 | 53;
|
int V9 = 0 << 16 | 53;
|
||||||
|
int V10 = 0 << 16 | 54;
|
||||||
|
|
||||||
// access flags
|
// access flags
|
||||||
|
|
||||||
@@ -70,18 +96,23 @@ public interface Opcodes {
|
|||||||
int ACC_FINAL = 0x0010; // class, field, method, parameter
|
int ACC_FINAL = 0x0010; // class, field, method, parameter
|
||||||
int ACC_SUPER = 0x0020; // class
|
int ACC_SUPER = 0x0020; // class
|
||||||
int ACC_SYNCHRONIZED = 0x0020; // method
|
int ACC_SYNCHRONIZED = 0x0020; // method
|
||||||
|
int ACC_OPEN = 0x0020; // module
|
||||||
|
int ACC_TRANSITIVE = 0x0020; // module requires
|
||||||
int ACC_VOLATILE = 0x0040; // field
|
int ACC_VOLATILE = 0x0040; // field
|
||||||
int ACC_BRIDGE = 0x0040; // method
|
int ACC_BRIDGE = 0x0040; // method
|
||||||
|
int ACC_STATIC_PHASE = 0x0040; // module requires
|
||||||
int ACC_VARARGS = 0x0080; // method
|
int ACC_VARARGS = 0x0080; // method
|
||||||
int ACC_TRANSIENT = 0x0080; // field
|
int ACC_TRANSIENT = 0x0080; // field
|
||||||
int ACC_NATIVE = 0x0100; // method
|
int ACC_NATIVE = 0x0100; // method
|
||||||
int ACC_INTERFACE = 0x0200; // class
|
int ACC_INTERFACE = 0x0200; // class
|
||||||
int ACC_ABSTRACT = 0x0400; // class, method
|
int ACC_ABSTRACT = 0x0400; // class, method
|
||||||
int ACC_STRICT = 0x0800; // method
|
int ACC_STRICT = 0x0800; // method
|
||||||
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter
|
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
|
||||||
int ACC_ANNOTATION = 0x2000; // class
|
int ACC_ANNOTATION = 0x2000; // class
|
||||||
int ACC_ENUM = 0x4000; // class(?) field inner
|
int ACC_ENUM = 0x4000; // class(?) field inner
|
||||||
int ACC_MANDATED = 0x8000; // parameter
|
int ACC_MANDATED = 0x8000; // parameter, module, module *
|
||||||
|
int ACC_MODULE = 0x8000; // class
|
||||||
|
|
||||||
|
|
||||||
// ASM specific pseudo access flags
|
// ASM specific pseudo access flags
|
||||||
|
|
||||||
@@ -148,15 +179,17 @@ public interface Opcodes {
|
|||||||
*/
|
*/
|
||||||
int F_SAME1 = 4;
|
int F_SAME1 = 4;
|
||||||
|
|
||||||
// For reference comparison purposes, construct new instances
|
// Do not try to change the following code to use auto-boxing,
|
||||||
// instead of using valueOf() or autoboxing.
|
// these values are compared by reference and not by value
|
||||||
Integer TOP = new Integer(0);
|
// The constructor of Integer was deprecated in 9
|
||||||
Integer INTEGER = new Integer(1);
|
// but we are stuck with it by backward compatibility
|
||||||
Integer FLOAT = new Integer(2);
|
@SuppressWarnings("deprecation") Integer TOP = new Integer(0);
|
||||||
Integer DOUBLE = new Integer(3);
|
@SuppressWarnings("deprecation") Integer INTEGER = new Integer(1);
|
||||||
Integer LONG = new Integer(4);
|
@SuppressWarnings("deprecation") Integer FLOAT = new Integer(2);
|
||||||
Integer NULL = new Integer(5);
|
@SuppressWarnings("deprecation") Integer DOUBLE = new Integer(3);
|
||||||
Integer UNINITIALIZED_THIS = new Integer(6);
|
@SuppressWarnings("deprecation") Integer LONG = new Integer(4);
|
||||||
|
@SuppressWarnings("deprecation") Integer NULL = new Integer(5);
|
||||||
|
@SuppressWarnings("deprecation") Integer UNINITIALIZED_THIS = new Integer(6);
|
||||||
|
|
||||||
// opcodes // visit method (- = idem)
|
// opcodes // visit method (- = idem)
|
||||||
|
|
||||||
|
|||||||
@@ -406,7 +406,16 @@ public class Type {
|
|||||||
*/
|
*/
|
||||||
public static Type getReturnType(final String methodDescriptor) {
|
public static Type getReturnType(final String methodDescriptor) {
|
||||||
char[] buf = methodDescriptor.toCharArray();
|
char[] buf = methodDescriptor.toCharArray();
|
||||||
return getType(buf, methodDescriptor.indexOf(')') + 1);
|
int off = 1;
|
||||||
|
while (true) {
|
||||||
|
char car = buf[off++];
|
||||||
|
if (car == ')') {
|
||||||
|
return getType(buf, off);
|
||||||
|
} else if (car == 'L') {
|
||||||
|
while (buf[off++] != ';') {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,427 +1,481 @@
|
|||||||
/*
|
/*
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||||
* To change this template file, choose Tools | Templates
|
*
|
||||||
* and open the template in the editor.
|
*
|
||||||
*/
|
*
|
||||||
package org.redkale.asm;
|
*
|
||||||
|
*
|
||||||
/**
|
*
|
||||||
* A reference to a type appearing in a class, field or method declaration, or
|
*
|
||||||
* on an instruction. Such a reference designates the part of the class where
|
*
|
||||||
* the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
|
*
|
||||||
* clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
|
*
|
||||||
* declaration, etc).
|
*
|
||||||
*
|
*
|
||||||
* @author Eric Bruneton
|
*
|
||||||
*/
|
*
|
||||||
public class TypeReference {
|
*
|
||||||
|
*
|
||||||
/**
|
*
|
||||||
* The sort of type references that target a type parameter of a generic
|
*
|
||||||
* class. See {@link #getSort getSort}.
|
*
|
||||||
*/
|
*
|
||||||
public final static int CLASS_TYPE_PARAMETER = 0x00;
|
*/
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* The sort of type references that target a type parameter of a generic
|
*
|
||||||
* method. See {@link #getSort getSort}.
|
*
|
||||||
*/
|
*
|
||||||
public final static int METHOD_TYPE_PARAMETER = 0x01;
|
*
|
||||||
|
*
|
||||||
/**
|
* ASM: a very small and fast Java bytecode manipulation framework
|
||||||
* The sort of type references that target the super class of a class or one
|
* Copyright (c) 2000-2013 INRIA, France Telecom
|
||||||
* of the interfaces it implements. See {@link #getSort getSort}.
|
* All rights reserved.
|
||||||
*/
|
*
|
||||||
public final static int CLASS_EXTENDS = 0x10;
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
/**
|
* are met:
|
||||||
* The sort of type references that target a bound of a type parameter of a
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
* generic class. See {@link #getSort getSort}.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
*/
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
/**
|
* 3. Neither the name of the copyright holders nor the names of its
|
||||||
* The sort of type references that target a bound of a type parameter of a
|
* contributors may be used to endorse or promote products derived from
|
||||||
* generic method. See {@link #getSort getSort}.
|
* this software without specific prior written permission.
|
||||||
*/
|
*
|
||||||
public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
/**
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
* The sort of type references that target the type of a field. See
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
* {@link #getSort getSort}.
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
*/
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
public final static int FIELD = 0x13;
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
/**
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
* The sort of type references that target the return type of a method. See
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
* {@link #getSort getSort}.
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
public final static int METHOD_RETURN = 0x14;
|
|
||||||
|
package org.redkale.asm;
|
||||||
/**
|
|
||||||
* The sort of type references that target the receiver type of a method.
|
/**
|
||||||
* See {@link #getSort getSort}.
|
* A reference to a type appearing in a class, field or method declaration, or
|
||||||
*/
|
* on an instruction. Such a reference designates the part of the class where
|
||||||
public final static int METHOD_RECEIVER = 0x15;
|
* the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
|
||||||
|
* clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
|
||||||
/**
|
* declaration, etc).
|
||||||
* The sort of type references that target the type of a formal parameter of
|
*
|
||||||
* a method. See {@link #getSort getSort}.
|
* @author Eric Bruneton
|
||||||
*/
|
*/
|
||||||
public final static int METHOD_FORMAL_PARAMETER = 0x16;
|
public class TypeReference {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target the type of an exception declared
|
* The sort of type references that target a type parameter of a generic
|
||||||
* in the throws clause of a method. See {@link #getSort getSort}.
|
* class. See {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int THROWS = 0x17;
|
public final static int CLASS_TYPE_PARAMETER = 0x00;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target the type of a local variable in a
|
* The sort of type references that target a type parameter of a generic
|
||||||
* method. See {@link #getSort getSort}.
|
* method. See {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int LOCAL_VARIABLE = 0x40;
|
public final static int METHOD_TYPE_PARAMETER = 0x01;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target the type of a resource variable
|
* The sort of type references that target the super class of a class or one
|
||||||
* in a method. See {@link #getSort getSort}.
|
* of the interfaces it implements. See {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int RESOURCE_VARIABLE = 0x41;
|
public final static int CLASS_EXTENDS = 0x10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target the type of the exception of a
|
* The sort of type references that target a bound of a type parameter of a
|
||||||
* 'catch' clause in a method. See {@link #getSort getSort}.
|
* generic class. See {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int EXCEPTION_PARAMETER = 0x42;
|
public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target the type declared in an
|
* The sort of type references that target a bound of a type parameter of a
|
||||||
* 'instanceof' instruction. See {@link #getSort getSort}.
|
* generic method. See {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int INSTANCEOF = 0x43;
|
public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target the type of the object created by
|
* The sort of type references that target the type of a field. See
|
||||||
* a 'new' instruction. See {@link #getSort getSort}.
|
* {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int NEW = 0x44;
|
public final static int FIELD = 0x13;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target the receiver type of a
|
* The sort of type references that target the return type of a method. See
|
||||||
* constructor reference. See {@link #getSort getSort}.
|
* {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int CONSTRUCTOR_REFERENCE = 0x45;
|
public final static int METHOD_RETURN = 0x14;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target the receiver type of a method
|
* The sort of type references that target the receiver type of a method.
|
||||||
* reference. See {@link #getSort getSort}.
|
* See {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int METHOD_REFERENCE = 0x46;
|
public final static int METHOD_RECEIVER = 0x15;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target the type declared in an explicit
|
* The sort of type references that target the type of a formal parameter of
|
||||||
* or implicit cast instruction. See {@link #getSort getSort}.
|
* a method. See {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int CAST = 0x47;
|
public final static int METHOD_FORMAL_PARAMETER = 0x16;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target a type parameter of a generic
|
* The sort of type references that target the type of an exception declared
|
||||||
* constructor in a constructor call. See {@link #getSort getSort}.
|
* in the throws clause of a method. See {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
|
public final static int THROWS = 0x17;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target a type parameter of a generic
|
* The sort of type references that target the type of a local variable in a
|
||||||
* method in a method call. See {@link #getSort getSort}.
|
* method. See {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
|
public final static int LOCAL_VARIABLE = 0x40;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target a type parameter of a generic
|
* The sort of type references that target the type of a resource variable
|
||||||
* constructor in a constructor reference. See {@link #getSort getSort}.
|
* in a method. See {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
|
public final static int RESOURCE_VARIABLE = 0x41;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sort of type references that target a type parameter of a generic
|
* The sort of type references that target the type of the exception of a
|
||||||
* method in a method reference. See {@link #getSort getSort}.
|
* 'catch' clause in a method. See {@link #getSort getSort}.
|
||||||
*/
|
*/
|
||||||
public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
|
public final static int EXCEPTION_PARAMETER = 0x42;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type reference value in Java class file format.
|
* The sort of type references that target the type declared in an
|
||||||
*/
|
* 'instanceof' instruction. See {@link #getSort getSort}.
|
||||||
private int value;
|
*/
|
||||||
|
public final static int INSTANCEOF = 0x43;
|
||||||
/**
|
|
||||||
* Creates a new TypeReference.
|
/**
|
||||||
*
|
* The sort of type references that target the type of the object created by
|
||||||
* @param typeRef
|
* a 'new' instruction. See {@link #getSort getSort}.
|
||||||
* the int encoded value of the type reference, as received in a
|
*/
|
||||||
* visit method related to type annotations, like
|
public final static int NEW = 0x44;
|
||||||
* visitTypeAnnotation.
|
|
||||||
*/
|
/**
|
||||||
public TypeReference(int typeRef) {
|
* The sort of type references that target the receiver type of a
|
||||||
this.value = typeRef;
|
* constructor reference. See {@link #getSort getSort}.
|
||||||
}
|
*/
|
||||||
|
public final static int CONSTRUCTOR_REFERENCE = 0x45;
|
||||||
/**
|
|
||||||
* Returns a type reference of the given sort.
|
/**
|
||||||
*
|
* The sort of type references that target the receiver type of a method
|
||||||
* @param sort
|
* reference. See {@link #getSort getSort}.
|
||||||
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
|
*/
|
||||||
* {@link #METHOD_RECEIVER METHOD_RECEIVER},
|
public final static int METHOD_REFERENCE = 0x46;
|
||||||
* {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
|
|
||||||
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
|
/**
|
||||||
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
|
* The sort of type references that target the type declared in an explicit
|
||||||
* {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
|
* or implicit cast instruction. See {@link #getSort getSort}.
|
||||||
* {@link #METHOD_REFERENCE METHOD_REFERENCE}.
|
*/
|
||||||
* @return a type reference of the given sort.
|
public final static int CAST = 0x47;
|
||||||
*/
|
|
||||||
public static TypeReference newTypeReference(int sort) {
|
/**
|
||||||
return new TypeReference(sort << 24);
|
* The sort of type references that target a type parameter of a generic
|
||||||
}
|
* constructor in a constructor call. See {@link #getSort getSort}.
|
||||||
|
*/
|
||||||
/**
|
public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
|
||||||
* Returns a reference to a type parameter of a generic class or method.
|
|
||||||
*
|
/**
|
||||||
* @param sort
|
* The sort of type references that target a type parameter of a generic
|
||||||
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
|
* method in a method call. See {@link #getSort getSort}.
|
||||||
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
|
*/
|
||||||
* @param paramIndex
|
public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
|
||||||
* the type parameter index.
|
|
||||||
* @return a reference to the given generic class or method type parameter.
|
/**
|
||||||
*/
|
* The sort of type references that target a type parameter of a generic
|
||||||
public static TypeReference newTypeParameterReference(int sort,
|
* constructor in a constructor reference. See {@link #getSort getSort}.
|
||||||
int paramIndex) {
|
*/
|
||||||
return new TypeReference((sort << 24) | (paramIndex << 16));
|
public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* The sort of type references that target a type parameter of a generic
|
||||||
* Returns a reference to a type parameter bound of a generic class or
|
* method in a method reference. See {@link #getSort getSort}.
|
||||||
* method.
|
*/
|
||||||
*
|
public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
|
||||||
* @param sort
|
|
||||||
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
|
/**
|
||||||
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
|
* The type reference value in Java class file format.
|
||||||
* @param paramIndex
|
*/
|
||||||
* the type parameter index.
|
private int value;
|
||||||
* @param boundIndex
|
|
||||||
* the type bound index within the above type parameters.
|
/**
|
||||||
* @return a reference to the given generic class or method type parameter
|
* Creates a new TypeReference.
|
||||||
* bound.
|
*
|
||||||
*/
|
* @param typeRef
|
||||||
public static TypeReference newTypeParameterBoundReference(int sort,
|
* the int encoded value of the type reference, as received in a
|
||||||
int paramIndex, int boundIndex) {
|
* visit method related to type annotations, like
|
||||||
return new TypeReference((sort << 24) | (paramIndex << 16)
|
* visitTypeAnnotation.
|
||||||
| (boundIndex << 8));
|
*/
|
||||||
}
|
public TypeReference(int typeRef) {
|
||||||
|
this.value = typeRef;
|
||||||
/**
|
}
|
||||||
* Returns a reference to the super class or to an interface of the
|
|
||||||
* 'implements' clause of a class.
|
/**
|
||||||
*
|
* Returns a type reference of the given sort.
|
||||||
* @param itfIndex
|
*
|
||||||
* the index of an interface in the 'implements' clause of a
|
* @param sort
|
||||||
* class, or -1 to reference the super class of the class.
|
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
|
||||||
* @return a reference to the given super type of a class.
|
* {@link #METHOD_RECEIVER METHOD_RECEIVER},
|
||||||
*/
|
* {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
|
||||||
public static TypeReference newSuperTypeReference(int itfIndex) {
|
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
|
||||||
itfIndex &= 0xFFFF;
|
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
|
||||||
return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
|
* {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
|
||||||
}
|
* {@link #METHOD_REFERENCE METHOD_REFERENCE}.
|
||||||
|
* @return a type reference of the given sort.
|
||||||
/**
|
*/
|
||||||
* Returns a reference to the type of a formal parameter of a method.
|
public static TypeReference newTypeReference(int sort) {
|
||||||
*
|
return new TypeReference(sort << 24);
|
||||||
* @param paramIndex
|
}
|
||||||
* the formal parameter index.
|
|
||||||
*
|
/**
|
||||||
* @return a reference to the type of the given method formal parameter.
|
* Returns a reference to a type parameter of a generic class or method.
|
||||||
*/
|
*
|
||||||
public static TypeReference newFormalParameterReference(int paramIndex) {
|
* @param sort
|
||||||
return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
|
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
|
||||||
| (paramIndex << 16));
|
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
|
||||||
}
|
* @param paramIndex
|
||||||
|
* the type parameter index.
|
||||||
/**
|
* @return a reference to the given generic class or method type parameter.
|
||||||
* Returns a reference to the type of an exception, in a 'throws' clause of
|
*/
|
||||||
* a method.
|
public static TypeReference newTypeParameterReference(int sort,
|
||||||
*
|
int paramIndex) {
|
||||||
* @param exceptionIndex
|
return new TypeReference((sort << 24) | (paramIndex << 16));
|
||||||
* the index of an exception in a 'throws' clause of a method.
|
}
|
||||||
*
|
|
||||||
* @return a reference to the type of the given exception.
|
/**
|
||||||
*/
|
* Returns a reference to a type parameter bound of a generic class or
|
||||||
public static TypeReference newExceptionReference(int exceptionIndex) {
|
* method.
|
||||||
return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
|
*
|
||||||
}
|
* @param sort
|
||||||
|
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
|
||||||
/**
|
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
|
||||||
* Returns a reference to the type of the exception declared in a 'catch'
|
* @param paramIndex
|
||||||
* clause of a method.
|
* the type parameter index.
|
||||||
*
|
* @param boundIndex
|
||||||
* @param tryCatchBlockIndex
|
* the type bound index within the above type parameters.
|
||||||
* the index of a try catch block (using the order in which they
|
* @return a reference to the given generic class or method type parameter
|
||||||
* are visited with visitTryCatchBlock).
|
* bound.
|
||||||
*
|
*/
|
||||||
* @return a reference to the type of the given exception.
|
public static TypeReference newTypeParameterBoundReference(int sort,
|
||||||
*/
|
int paramIndex, int boundIndex) {
|
||||||
public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
|
return new TypeReference((sort << 24) | (paramIndex << 16)
|
||||||
return new TypeReference((EXCEPTION_PARAMETER << 24)
|
| (boundIndex << 8));
|
||||||
| (tryCatchBlockIndex << 8));
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Returns a reference to the super class or to an interface of the
|
||||||
* Returns a reference to the type of a type argument in a constructor or
|
* 'implements' clause of a class.
|
||||||
* method call or reference.
|
*
|
||||||
*
|
* @param itfIndex
|
||||||
* @param sort
|
* the index of an interface in the 'implements' clause of a
|
||||||
* {@link #CAST CAST},
|
* class, or -1 to reference the super class of the class.
|
||||||
* {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
|
* @return a reference to the given super type of a class.
|
||||||
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
|
*/
|
||||||
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT
|
public static TypeReference newSuperTypeReference(int itfIndex) {
|
||||||
* METHOD_INVOCATION_TYPE_ARGUMENT},
|
itfIndex &= 0xFFFF;
|
||||||
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
|
return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
|
||||||
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
|
}
|
||||||
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT
|
|
||||||
* METHOD_REFERENCE_TYPE_ARGUMENT}.
|
/**
|
||||||
* @param argIndex
|
* Returns a reference to the type of a formal parameter of a method.
|
||||||
* the type argument index.
|
*
|
||||||
*
|
* @param paramIndex
|
||||||
* @return a reference to the type of the given type argument.
|
* the formal parameter index.
|
||||||
*/
|
*
|
||||||
public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
|
* @return a reference to the type of the given method formal parameter.
|
||||||
return new TypeReference((sort << 24) | argIndex);
|
*/
|
||||||
}
|
public static TypeReference newFormalParameterReference(int paramIndex) {
|
||||||
|
return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
|
||||||
/**
|
| (paramIndex << 16));
|
||||||
* Returns the sort of this type reference.
|
}
|
||||||
*
|
|
||||||
* @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
|
/**
|
||||||
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
|
* Returns a reference to the type of an exception, in a 'throws' clause of
|
||||||
* {@link #CLASS_EXTENDS CLASS_EXTENDS},
|
* a method.
|
||||||
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
|
*
|
||||||
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
|
* @param exceptionIndex
|
||||||
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
|
* the index of an exception in a 'throws' clause of a method.
|
||||||
* {@link #METHOD_RECEIVER METHOD_RECEIVER},
|
*
|
||||||
* {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},
|
* @return a reference to the type of the given exception.
|
||||||
* {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
|
*/
|
||||||
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
|
public static TypeReference newExceptionReference(int exceptionIndex) {
|
||||||
* {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
|
return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
|
||||||
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
|
}
|
||||||
* {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
|
|
||||||
* {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},
|
/**
|
||||||
* {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
|
* Returns a reference to the type of the exception declared in a 'catch'
|
||||||
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
|
* clause of a method.
|
||||||
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT
|
*
|
||||||
* METHOD_INVOCATION_TYPE_ARGUMENT},
|
* @param tryCatchBlockIndex
|
||||||
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
|
* the index of a try catch block (using the order in which they
|
||||||
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
|
* are visited with visitTryCatchBlock).
|
||||||
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT
|
*
|
||||||
* METHOD_REFERENCE_TYPE_ARGUMENT}.
|
* @return a reference to the type of the given exception.
|
||||||
*/
|
*/
|
||||||
public int getSort() {
|
public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
|
||||||
return value >>> 24;
|
return new TypeReference((EXCEPTION_PARAMETER << 24)
|
||||||
}
|
| (tryCatchBlockIndex << 8));
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Returns the index of the type parameter referenced by this type
|
/**
|
||||||
* reference. This method must only be used for type references whose sort
|
* Returns a reference to the type of a type argument in a constructor or
|
||||||
* is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
|
* method call or reference.
|
||||||
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
|
*
|
||||||
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
|
* @param sort
|
||||||
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
|
* {@link #CAST CAST},
|
||||||
*
|
* {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
|
||||||
* @return a type parameter index.
|
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
|
||||||
*/
|
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT
|
||||||
public int getTypeParameterIndex() {
|
* METHOD_INVOCATION_TYPE_ARGUMENT},
|
||||||
return (value & 0x00FF0000) >> 16;
|
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
|
||||||
}
|
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
|
||||||
|
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT
|
||||||
/**
|
* METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||||
* Returns the index of the type parameter bound, within the type parameter
|
* @param argIndex
|
||||||
* {@link #getTypeParameterIndex}, referenced by this type reference. This
|
* the type argument index.
|
||||||
* method must only be used for type references whose sort is
|
*
|
||||||
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
|
* @return a reference to the type of the given type argument.
|
||||||
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
|
*/
|
||||||
*
|
public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
|
||||||
* @return a type parameter bound index.
|
return new TypeReference((sort << 24) | argIndex);
|
||||||
*/
|
}
|
||||||
public int getTypeParameterBoundIndex() {
|
|
||||||
return (value & 0x0000FF00) >> 8;
|
/**
|
||||||
}
|
* Returns the sort of this type reference.
|
||||||
|
*
|
||||||
/**
|
* @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
|
||||||
* Returns the index of the "super type" of a class that is referenced by
|
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
|
||||||
* this type reference. This method must only be used for type references
|
* {@link #CLASS_EXTENDS CLASS_EXTENDS},
|
||||||
* whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
|
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
|
||||||
*
|
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
|
||||||
* @return the index of an interface in the 'implements' clause of a class,
|
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
|
||||||
* or -1 if this type reference references the type of the super
|
* {@link #METHOD_RECEIVER METHOD_RECEIVER},
|
||||||
* class.
|
* {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},
|
||||||
*/
|
* {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
|
||||||
public int getSuperTypeIndex() {
|
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
|
||||||
return (short) ((value & 0x00FFFF00) >> 8);
|
* {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
|
||||||
}
|
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
|
||||||
|
* {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
|
||||||
/**
|
* {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},
|
||||||
* Returns the index of the formal parameter whose type is referenced by
|
* {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
|
||||||
* this type reference. This method must only be used for type references
|
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
|
||||||
* whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
|
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT
|
||||||
*
|
* METHOD_INVOCATION_TYPE_ARGUMENT},
|
||||||
* @return a formal parameter index.
|
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
|
||||||
*/
|
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
|
||||||
public int getFormalParameterIndex() {
|
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT
|
||||||
return (value & 0x00FF0000) >> 16;
|
* METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||||
}
|
*/
|
||||||
|
public int getSort() {
|
||||||
/**
|
return value >>> 24;
|
||||||
* Returns the index of the exception, in a 'throws' clause of a method,
|
}
|
||||||
* whose type is referenced by this type reference. This method must only be
|
|
||||||
* used for type references whose sort is {@link #THROWS THROWS}.
|
/**
|
||||||
*
|
* Returns the index of the type parameter referenced by this type
|
||||||
* @return the index of an exception in the 'throws' clause of a method.
|
* reference. This method must only be used for type references whose sort
|
||||||
*/
|
* is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
|
||||||
public int getExceptionIndex() {
|
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
|
||||||
return (value & 0x00FFFF00) >> 8;
|
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
|
||||||
}
|
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
|
||||||
|
*
|
||||||
/**
|
* @return a type parameter index.
|
||||||
* Returns the index of the try catch block (using the order in which they
|
*/
|
||||||
* are visited with visitTryCatchBlock), whose 'catch' type is referenced by
|
public int getTypeParameterIndex() {
|
||||||
* this type reference. This method must only be used for type references
|
return (value & 0x00FF0000) >> 16;
|
||||||
* whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
|
}
|
||||||
*
|
|
||||||
* @return the index of an exception in the 'throws' clause of a method.
|
/**
|
||||||
*/
|
* Returns the index of the type parameter bound, within the type parameter
|
||||||
public int getTryCatchBlockIndex() {
|
* {@link #getTypeParameterIndex}, referenced by this type reference. This
|
||||||
return (value & 0x00FFFF00) >> 8;
|
* method must only be used for type references whose sort is
|
||||||
}
|
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
|
||||||
|
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
|
||||||
/**
|
*
|
||||||
* Returns the index of the type argument referenced by this type reference.
|
* @return a type parameter bound index.
|
||||||
* This method must only be used for type references whose sort is
|
*/
|
||||||
* {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
|
public int getTypeParameterBoundIndex() {
|
||||||
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
|
return (value & 0x0000FF00) >> 8;
|
||||||
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
|
}
|
||||||
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
|
|
||||||
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
|
/**
|
||||||
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
|
* Returns the index of the "super type" of a class that is referenced by
|
||||||
*
|
* this type reference. This method must only be used for type references
|
||||||
* @return a type parameter index.
|
* whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
|
||||||
*/
|
*
|
||||||
public int getTypeArgumentIndex() {
|
* @return the index of an interface in the 'implements' clause of a class,
|
||||||
return value & 0xFF;
|
* or -1 if this type reference references the type of the super
|
||||||
}
|
* class.
|
||||||
|
*/
|
||||||
/**
|
public int getSuperTypeIndex() {
|
||||||
* Returns the int encoded value of this type reference, suitable for use in
|
return (short) ((value & 0x00FFFF00) >> 8);
|
||||||
* visit methods related to type annotations, like visitTypeAnnotation.
|
}
|
||||||
*
|
|
||||||
* @return the int encoded value of this type reference.
|
/**
|
||||||
*/
|
* Returns the index of the formal parameter whose type is referenced by
|
||||||
public int getValue() {
|
* this type reference. This method must only be used for type references
|
||||||
return value;
|
* whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
|
||||||
}
|
*
|
||||||
}
|
* @return a formal parameter index.
|
||||||
|
*/
|
||||||
|
public int getFormalParameterIndex() {
|
||||||
|
return (value & 0x00FF0000) >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the exception, in a 'throws' clause of a method,
|
||||||
|
* whose type is referenced by this type reference. This method must only be
|
||||||
|
* used for type references whose sort is {@link #THROWS THROWS}.
|
||||||
|
*
|
||||||
|
* @return the index of an exception in the 'throws' clause of a method.
|
||||||
|
*/
|
||||||
|
public int getExceptionIndex() {
|
||||||
|
return (value & 0x00FFFF00) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the try catch block (using the order in which they
|
||||||
|
* are visited with visitTryCatchBlock), whose 'catch' type is referenced by
|
||||||
|
* this type reference. This method must only be used for type references
|
||||||
|
* whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
|
||||||
|
*
|
||||||
|
* @return the index of an exception in the 'throws' clause of a method.
|
||||||
|
*/
|
||||||
|
public int getTryCatchBlockIndex() {
|
||||||
|
return (value & 0x00FFFF00) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the type argument referenced by this type reference.
|
||||||
|
* This method must only be used for type references whose sort is
|
||||||
|
* {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
|
||||||
|
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
|
||||||
|
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
|
||||||
|
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
|
||||||
|
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
|
||||||
|
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||||
|
*
|
||||||
|
* @return a type parameter index.
|
||||||
|
*/
|
||||||
|
public int getTypeArgumentIndex() {
|
||||||
|
return value & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the int encoded value of this type reference, suitable for use in
|
||||||
|
* visit methods related to type annotations, like visitTypeAnnotation.
|
||||||
|
*
|
||||||
|
* @return the int encoded value of this type reference.
|
||||||
|
*/
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ public final class ApiDocsService {
|
|||||||
for (final Class rtype : action.results()) {
|
for (final Class rtype : action.results()) {
|
||||||
results.add(rtype.getName());
|
results.add(rtype.getName());
|
||||||
if (typesmap.containsKey(rtype.getName())) continue;
|
if (typesmap.containsKey(rtype.getName())) continue;
|
||||||
|
if(rtype.getName().startsWith("java.")) continue;
|
||||||
|
if(rtype.getName().startsWith("javax.")) continue;
|
||||||
final boolean filter = FilterBean.class.isAssignableFrom(rtype);
|
final boolean filter = FilterBean.class.isAssignableFrom(rtype);
|
||||||
final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>();
|
final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>();
|
||||||
Class loop = rtype;
|
Class loop = rtype;
|
||||||
@@ -136,6 +138,8 @@ public final class ApiDocsService {
|
|||||||
paramsList.add(parammap);
|
paramsList.add(parammap);
|
||||||
if (ptype.isPrimitive() || ptype == String.class) continue;
|
if (ptype.isPrimitive() || ptype == String.class) continue;
|
||||||
if (typesmap.containsKey(ptype.getName())) continue;
|
if (typesmap.containsKey(ptype.getName())) continue;
|
||||||
|
if(ptype.getName().startsWith("java.")) continue;
|
||||||
|
if(ptype.getName().startsWith("javax.")) continue;
|
||||||
|
|
||||||
final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>();
|
final Map<String, Map<String, Object>> typemap = new LinkedHashMap<>();
|
||||||
Class loop = ptype;
|
Class loop = ptype;
|
||||||
@@ -192,7 +196,7 @@ public final class ApiDocsService {
|
|||||||
final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "apidoc.json"));
|
final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "apidoc.json"));
|
||||||
out.write(json.getBytes("UTF-8"));
|
out.write(json.getBytes("UTF-8"));
|
||||||
out.close();
|
out.close();
|
||||||
File doctemplate = new File(app.getHome(), "conf/apidoc-template.html");
|
File doctemplate = new File(app.getConfPath(), "apidoc-template.html");
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
if (doctemplate.isFile() && doctemplate.canRead()) {
|
if (doctemplate.isFile() && doctemplate.canRead()) {
|
||||||
in = new FileInputStream(doctemplate);
|
in = new FileInputStream(doctemplate);
|
||||||
|
|||||||
@@ -61,6 +61,11 @@ public final class Application {
|
|||||||
*/
|
*/
|
||||||
public static final String RESNAME_APP_HOME = "APP_HOME";
|
public static final String RESNAME_APP_HOME = "APP_HOME";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前进程的配置目录,如果不是绝对路径则视为HOME目录下的相对路径 类型:String、File、Path
|
||||||
|
*/
|
||||||
|
public static final String RESNAME_APP_CONF = "APP_CONF";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* application.xml 文件中resources节点的内容, 类型: AnyValue
|
* application.xml 文件中resources节点的内容, 类型: AnyValue
|
||||||
*/
|
*/
|
||||||
@@ -96,6 +101,11 @@ public final class Application {
|
|||||||
*/
|
*/
|
||||||
public static final String RESNAME_SERVER_EXECUTOR = Server.RESNAME_SERVER_EXECUTOR;
|
public static final String RESNAME_SERVER_EXECUTOR = Server.RESNAME_SERVER_EXECUTOR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前Server的ResourceFactory
|
||||||
|
*/
|
||||||
|
public static final String RESNAME_SERVER_RESFACTORY = Server.RESNAME_SERVER_RESFACTORY;
|
||||||
|
|
||||||
//本地IP地址
|
//本地IP地址
|
||||||
final InetAddress localAddress;
|
final InetAddress localAddress;
|
||||||
|
|
||||||
@@ -132,6 +142,9 @@ public final class Application {
|
|||||||
//进程根目录
|
//进程根目录
|
||||||
private final File home;
|
private final File home;
|
||||||
|
|
||||||
|
//配置文件目录
|
||||||
|
private final File confPath;
|
||||||
|
|
||||||
//日志
|
//日志
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
@@ -157,6 +170,7 @@ public final class Application {
|
|||||||
private Application(final boolean singletonrun, final AnyValue config) {
|
private Application(final boolean singletonrun, final AnyValue config) {
|
||||||
this.singletonrun = singletonrun;
|
this.singletonrun = singletonrun;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
System.setProperty("redkale.version", Redkale.getDotedVersion());
|
||||||
|
|
||||||
final File root = new File(System.getProperty(RESNAME_APP_HOME));
|
final File root = new File(System.getProperty(RESNAME_APP_HOME));
|
||||||
this.resourceFactory.register(RESNAME_APP_TIME, long.class, this.startTime);
|
this.resourceFactory.register(RESNAME_APP_TIME, long.class, this.startTime);
|
||||||
@@ -165,6 +179,12 @@ public final class Application {
|
|||||||
try {
|
try {
|
||||||
this.resourceFactory.register(RESNAME_APP_HOME, root.getCanonicalPath());
|
this.resourceFactory.register(RESNAME_APP_HOME, root.getCanonicalPath());
|
||||||
this.home = root.getCanonicalFile();
|
this.home = root.getCanonicalFile();
|
||||||
|
String confsubpath = System.getProperty(RESNAME_APP_CONF, "conf");
|
||||||
|
if (confsubpath.charAt(0) == '/' || confsubpath.indexOf(':') > 0) {
|
||||||
|
this.confPath = new File(confsubpath).getCanonicalFile();
|
||||||
|
} else {
|
||||||
|
this.confPath = new File(this.home, confsubpath).getCanonicalFile();
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -189,7 +209,7 @@ public final class Application {
|
|||||||
System.setProperty(RESNAME_APP_NODE, node);
|
System.setProperty(RESNAME_APP_NODE, node);
|
||||||
}
|
}
|
||||||
//以下是初始化日志配置
|
//以下是初始化日志配置
|
||||||
final File logconf = new File(root, "conf/logging.properties");
|
final File logconf = new File(confPath, "logging.properties");
|
||||||
if (logconf.isFile() && logconf.canRead()) {
|
if (logconf.isFile() && logconf.canRead()) {
|
||||||
try {
|
try {
|
||||||
final String rootpath = root.getCanonicalPath().replace('\\', '/');
|
final String rootpath = root.getCanonicalPath().replace('\\', '/');
|
||||||
@@ -249,8 +269,8 @@ public final class Application {
|
|||||||
TransportStrategy strategy = null;
|
TransportStrategy strategy = null;
|
||||||
int bufferCapacity = 32 * 1024;
|
int bufferCapacity = 32 * 1024;
|
||||||
int bufferPoolSize = Runtime.getRuntime().availableProcessors() * 8;
|
int bufferPoolSize = Runtime.getRuntime().availableProcessors() * 8;
|
||||||
int readTimeoutSecond = TransportFactory.DEFAULT_READTIMEOUTSECOND;
|
int readTimeoutSeconds = TransportFactory.DEFAULT_READTIMEOUTSECONDS;
|
||||||
int writeTimeoutSecond = TransportFactory.DEFAULT_WRITETIMEOUTSECOND;
|
int writeTimeoutSeconds = TransportFactory.DEFAULT_WRITETIMEOUTSECONDS;
|
||||||
AtomicLong createBufferCounter = new AtomicLong();
|
AtomicLong createBufferCounter = new AtomicLong();
|
||||||
AtomicLong cycleBufferCounter = new AtomicLong();
|
AtomicLong cycleBufferCounter = new AtomicLong();
|
||||||
if (resources != null) {
|
if (resources != null) {
|
||||||
@@ -260,8 +280,8 @@ public final class Application {
|
|||||||
if (transportConf != null) {
|
if (transportConf != null) {
|
||||||
//--------------transportBufferPool-----------
|
//--------------transportBufferPool-----------
|
||||||
bufferCapacity = Math.max(parseLenth(transportConf.getValue("bufferCapacity"), bufferCapacity), 8 * 1024);
|
bufferCapacity = Math.max(parseLenth(transportConf.getValue("bufferCapacity"), bufferCapacity), 8 * 1024);
|
||||||
readTimeoutSecond = transportConf.getIntValue("readTimeoutSecond", readTimeoutSecond);
|
readTimeoutSeconds = transportConf.getIntValue("readTimeoutSeconds", readTimeoutSeconds);
|
||||||
writeTimeoutSecond = transportConf.getIntValue("writeTimeoutSecond", writeTimeoutSecond);
|
writeTimeoutSeconds = transportConf.getIntValue("writeTimeoutSeconds", writeTimeoutSeconds);
|
||||||
final int threads = parseLenth(transportConf.getValue("threads"), groupsize * Runtime.getRuntime().availableProcessors() * 2);
|
final int threads = parseLenth(transportConf.getValue("threads"), groupsize * Runtime.getRuntime().availableProcessors() * 2);
|
||||||
bufferPoolSize = parseLenth(transportConf.getValue("bufferPoolSize"), threads * 4);
|
bufferPoolSize = parseLenth(transportConf.getValue("bufferPoolSize"), threads * 4);
|
||||||
final int capacity = bufferCapacity;
|
final int capacity = bufferCapacity;
|
||||||
@@ -275,7 +295,7 @@ public final class Application {
|
|||||||
try {
|
try {
|
||||||
final String strategyClass = transportConf.getValue("strategy");
|
final String strategyClass = transportConf.getValue("strategy");
|
||||||
if (strategyClass != null && !strategyClass.isEmpty()) {
|
if (strategyClass != null && !strategyClass.isEmpty()) {
|
||||||
strategy = (TransportStrategy) classLoader.loadClass(strategyClass).newInstance();
|
strategy = (TransportStrategy) classLoader.loadClass(strategyClass).getDeclaredConstructor().newInstance();
|
||||||
}
|
}
|
||||||
final AtomicInteger counter = new AtomicInteger();
|
final AtomicInteger counter = new AtomicInteger();
|
||||||
transportExec = Executors.newFixedThreadPool(threads, (Runnable r) -> {
|
transportExec = Executors.newFixedThreadPool(threads, (Runnable r) -> {
|
||||||
@@ -314,8 +334,10 @@ public final class Application {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.sncpTransportFactory = TransportFactory.create(transportExec, transportPool, transportGroup, (SSLContext) null, readTimeoutSecond, writeTimeoutSecond, strategy);
|
this.sncpTransportFactory = TransportFactory.create(transportExec, transportPool, transportGroup, (SSLContext) null, readTimeoutSeconds, writeTimeoutSeconds, strategy);
|
||||||
DefaultAnyValue tarnsportConf = DefaultAnyValue.create(TransportFactory.NAME_PINGINTERVAL, System.getProperty("net.transport.pinginterval", "30"));
|
DefaultAnyValue tarnsportConf = DefaultAnyValue.create(TransportFactory.NAME_POOLMAXCONNS, System.getProperty("net.transport.poolmaxconns", "100"))
|
||||||
|
.addValue(TransportFactory.NAME_PINGINTERVAL, System.getProperty("net.transport.pinginterval", "30"))
|
||||||
|
.addValue(TransportFactory.NAME_CHECKINTERVAL, System.getProperty("net.transport.checkinterval", "30"));
|
||||||
this.sncpTransportFactory.init(tarnsportConf, Sncp.PING_BUFFER, Sncp.PONG_BUFFER.remaining());
|
this.sncpTransportFactory.init(tarnsportConf, Sncp.PING_BUFFER, Sncp.PONG_BUFFER.remaining());
|
||||||
Thread.currentThread().setContextClassLoader(this.classLoader);
|
Thread.currentThread().setContextClassLoader(this.classLoader);
|
||||||
this.serverClassLoader = new RedkaleClassLoader(this.classLoader);
|
this.serverClassLoader = new RedkaleClassLoader(this.classLoader);
|
||||||
@@ -341,10 +363,22 @@ public final class Application {
|
|||||||
return new ArrayList<>(servers);
|
return new ArrayList<>(servers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<DataSource> getDataSources() {
|
||||||
|
return new ArrayList<>(dataSources);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CacheSource> getCacheSources() {
|
||||||
|
return new ArrayList<>(cacheSources);
|
||||||
|
}
|
||||||
|
|
||||||
public File getHome() {
|
public File getHome() {
|
||||||
return home;
|
return home;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public File getConfPath() {
|
||||||
|
return confPath;
|
||||||
|
}
|
||||||
|
|
||||||
public long getStartTime() {
|
public long getStartTime() {
|
||||||
return startTime;
|
return startTime;
|
||||||
}
|
}
|
||||||
@@ -354,8 +388,9 @@ public final class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void init() throws Exception {
|
public void init() throws Exception {
|
||||||
System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "" + Runtime.getRuntime().availableProcessors() * 4);
|
System.setProperty("net.transport.poolmaxconns", "100");
|
||||||
System.setProperty("net.transport.pinginterval", "30");
|
System.setProperty("net.transport.pinginterval", "30");
|
||||||
|
System.setProperty("net.transport.checkinterval", "30");
|
||||||
System.setProperty("convert.bson.tiny", "true");
|
System.setProperty("convert.bson.tiny", "true");
|
||||||
System.setProperty("convert.json.tiny", "true");
|
System.setProperty("convert.json.tiny", "true");
|
||||||
System.setProperty("convert.bson.pool.size", "128");
|
System.setProperty("convert.bson.pool.size", "128");
|
||||||
@@ -363,12 +398,21 @@ public final class Application {
|
|||||||
System.setProperty("convert.bson.writer.buffer.defsize", "4096");
|
System.setProperty("convert.bson.writer.buffer.defsize", "4096");
|
||||||
System.setProperty("convert.json.writer.buffer.defsize", "4096");
|
System.setProperty("convert.json.writer.buffer.defsize", "4096");
|
||||||
|
|
||||||
File persist = new File(this.home, "conf/persistence.xml");
|
File persist = new File(this.confPath, "persistence.xml");
|
||||||
final String homepath = this.home.getCanonicalPath();
|
final String homepath = this.home.getCanonicalPath();
|
||||||
|
final String confpath = this.confPath.getCanonicalPath();
|
||||||
if (persist.isFile()) System.setProperty(DataSources.DATASOURCE_CONFPATH, persist.getCanonicalPath());
|
if (persist.isFile()) System.setProperty(DataSources.DATASOURCE_CONFPATH, persist.getCanonicalPath());
|
||||||
logger.log(Level.INFO, "APP_JAVA = " + System.getProperty("java.version") + "\r\n" + RESNAME_APP_ADDR + " = " + this.localAddress.getHostAddress() + "\r\n" + RESNAME_APP_HOME + " = " + homepath);
|
String pidstr = "";
|
||||||
|
try { //JDK 9+
|
||||||
|
Class phclass = Class.forName("java.lang.ProcessHandle");
|
||||||
|
Object phobj = phclass.getMethod("current").invoke(null);
|
||||||
|
Object pid = phclass.getMethod("pid").invoke(phobj);
|
||||||
|
pidstr = "APP_PID = " + pid + "\r\n";
|
||||||
|
} catch (Throwable t) {
|
||||||
|
}
|
||||||
|
logger.log(Level.INFO, pidstr + "APP_JAVA = " + System.getProperty("java.version") + "\r\n" + RESNAME_APP_ADDR + " = " + this.localAddress.getHostAddress() + "\r\n" + RESNAME_APP_HOME + " = " + homepath + "\r\n" + RESNAME_APP_CONF + " = " + confpath);
|
||||||
String lib = config.getValue("lib", "${APP_HOME}/libs/*").trim().replace("${APP_HOME}", homepath);
|
String lib = config.getValue("lib", "${APP_HOME}/libs/*").trim().replace("${APP_HOME}", homepath);
|
||||||
lib = lib.isEmpty() ? (homepath + "/conf") : (lib + ";" + homepath + "/conf");
|
lib = lib.isEmpty() ? confpath : (lib + ";" + confpath);
|
||||||
Server.loadLib(classLoader, logger, lib);
|
Server.loadLib(classLoader, logger, lib);
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
@@ -381,13 +425,13 @@ public final class Application {
|
|||||||
if (dfloads != null) {
|
if (dfloads != null) {
|
||||||
for (String dfload : dfloads.split(";")) {
|
for (String dfload : dfloads.split(";")) {
|
||||||
if (dfload.trim().isEmpty()) continue;
|
if (dfload.trim().isEmpty()) continue;
|
||||||
final File df = (dfload.indexOf('/') < 0) ? new File(home, "conf/" + dfload) : new File(dfload);
|
final File df = (dfload.indexOf('/') < 0) ? new File(confPath, "/" + dfload) : new File(dfload);
|
||||||
if (df.isFile()) {
|
if (df.isFile()) {
|
||||||
Properties ps = new Properties();
|
Properties ps = new Properties();
|
||||||
InputStream in = new FileInputStream(df);
|
InputStream in = new FileInputStream(df);
|
||||||
ps.load(in);
|
ps.load(in);
|
||||||
in.close();
|
in.close();
|
||||||
ps.forEach((x, y) -> resourceFactory.register("property." + x, y));
|
ps.forEach((x, y) -> resourceFactory.register("property." + x, y.toString().replace("${APP_HOME}", homepath)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,6 +439,7 @@ public final class Application {
|
|||||||
String name = prop.getValue("name");
|
String name = prop.getValue("name");
|
||||||
String value = prop.getValue("value");
|
String value = prop.getValue("value");
|
||||||
if (name == null || value == null) continue;
|
if (name == null || value == null) continue;
|
||||||
|
value = value.replace("${APP_HOME}", homepath);
|
||||||
if (name.startsWith("system.property.")) {
|
if (name.startsWith("system.property.")) {
|
||||||
System.setProperty(name.substring("system.property.".length()), value);
|
System.setProperty(name.substring("system.property.".length()), value);
|
||||||
} else if (name.startsWith("mimetype.property.")) {
|
} else if (name.startsWith("mimetype.property.")) {
|
||||||
@@ -422,12 +467,13 @@ public final class Application {
|
|||||||
try {
|
try {
|
||||||
Resource res = field.getAnnotation(Resource.class);
|
Resource res = field.getAnnotation(Resource.class);
|
||||||
if (res == null) return;
|
if (res == null) return;
|
||||||
if (Sncp.isRemote((Service) src)) return; //远程模式不得注入
|
if (src instanceof Service && Sncp.isRemote((Service) src)) return; //远程模式不得注入
|
||||||
Class type = field.getType();
|
Class type = field.getType();
|
||||||
if (type == Application.class) {
|
if (type == Application.class) {
|
||||||
field.set(src, application);
|
field.set(src, application);
|
||||||
} else if (type == ResourceFactory.class) {
|
} else if (type == ResourceFactory.class) {
|
||||||
field.set(src, res.name().equalsIgnoreCase("server") ? rf : (res.name().isEmpty() ? application.resourceFactory : null));
|
boolean serv = RESNAME_SERVER_RESFACTORY.equals(res.name()) || res.name().equalsIgnoreCase("server");
|
||||||
|
field.set(src, serv ? rf : (res.name().isEmpty() ? application.resourceFactory : null));
|
||||||
} else if (type == TransportFactory.class) {
|
} else if (type == TransportFactory.class) {
|
||||||
field.set(src, application.sncpTransportFactory);
|
field.set(src, application.sncpTransportFactory);
|
||||||
} else if (type == NodeSncpServer.class) {
|
} else if (type == NodeSncpServer.class) {
|
||||||
@@ -502,7 +548,8 @@ public final class Application {
|
|||||||
if (listenClass.isEmpty()) continue;
|
if (listenClass.isEmpty()) continue;
|
||||||
Class clazz = classLoader.loadClass(listenClass);
|
Class clazz = classLoader.loadClass(listenClass);
|
||||||
if (!ApplicationListener.class.isAssignableFrom(clazz)) continue;
|
if (!ApplicationListener.class.isAssignableFrom(clazz)) continue;
|
||||||
ApplicationListener listener = (ApplicationListener) clazz.newInstance();
|
@SuppressWarnings("unchecked")
|
||||||
|
ApplicationListener listener = (ApplicationListener) clazz.getDeclaredConstructor().newInstance();
|
||||||
listener.init(config);
|
listener.init(config);
|
||||||
this.listeners.add(listener);
|
this.listeners.add(listener);
|
||||||
}
|
}
|
||||||
@@ -512,8 +559,8 @@ public final class Application {
|
|||||||
|
|
||||||
public void restoreConfig() throws IOException {
|
public void restoreConfig() throws IOException {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
File confFile = new File(this.home, "conf/application.xml");
|
File confFile = new File(this.confPath, "application.xml");
|
||||||
confFile.renameTo(new File(this.home, "conf/application_" + String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$tS", System.currentTimeMillis()) + ".xml"));
|
confFile.renameTo(new File(this.confPath, "application_" + String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$tS", System.currentTimeMillis()) + ".xml"));
|
||||||
final PrintStream ps = new PrintStream(new FileOutputStream(confFile));
|
final PrintStream ps = new PrintStream(new FileOutputStream(confFile));
|
||||||
ps.append(config.toXML("application"));
|
ps.append(config.toXML("application"));
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -594,15 +641,15 @@ public final class Application {
|
|||||||
buffer.flip();
|
buffer.flip();
|
||||||
channel.write(buffer);
|
channel.write(buffer);
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
channel.configureBlocking(false);
|
channel.configureBlocking(true);
|
||||||
try {
|
try {
|
||||||
channel.read(buffer);
|
channel.read(buffer);
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
byte[] bytes = new byte[buffer.remaining()];
|
byte[] bytes = new byte[buffer.remaining()];
|
||||||
buffer.get(bytes);
|
buffer.get(bytes);
|
||||||
channel.close();
|
channel.close();
|
||||||
logger.info(new String(bytes));
|
logger.info("Send: " + command + ", Reply: " + new String(bytes));
|
||||||
Thread.sleep(500);
|
Thread.sleep(1000);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (e instanceof PortUnreachableException) {
|
if (e instanceof PortUnreachableException) {
|
||||||
if ("APIDOC".equalsIgnoreCase(command)) {
|
if ("APIDOC".equalsIgnoreCase(command)) {
|
||||||
@@ -641,19 +688,21 @@ public final class Application {
|
|||||||
runServers(timecd, watchs); //必须在所有服务都启动后再启动WATCH服务
|
runServers(timecd, watchs); //必须在所有服务都启动后再启动WATCH服务
|
||||||
timecd.await();
|
timecd.await();
|
||||||
//if (!singletonrun) signalHandle();
|
//if (!singletonrun) signalHandle();
|
||||||
if (!singletonrun) clearPersistData();
|
//if (!singletonrun) clearPersistData();
|
||||||
logger.info(this.getClass().getSimpleName() + " started in " + (System.currentTimeMillis() - startTime) + " ms\r\n");
|
logger.info(this.getClass().getSimpleName() + " started in " + (System.currentTimeMillis() - startTime) + " ms\r\n");
|
||||||
if (!singletonrun) this.serversLatch.await();
|
if (!singletonrun) this.serversLatch.await();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearPersistData() {
|
// private void clearPersistData() {
|
||||||
File cachedir = new File(home, "cache");
|
// File cachedir = new File(home, "cache");
|
||||||
if (!cachedir.isDirectory()) return;
|
// if (!cachedir.isDirectory()) return;
|
||||||
for (File file : cachedir.listFiles()) {
|
// File[] lfs = cachedir.listFiles();
|
||||||
if (file.getName().startsWith("persist-")) file.delete();
|
// if (lfs != null) {
|
||||||
}
|
// for (File file : lfs) {
|
||||||
}
|
// if (file.getName().startsWith("persist-")) file.delete();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
// private void signalHandle() {
|
// private void signalHandle() {
|
||||||
// //http://www.comptechdoc.org/os/linux/programming/linux_pgsignals.html
|
// //http://www.comptechdoc.org/os/linux/programming/linux_pgsignals.html
|
||||||
// String[] sigs = new String[]{"HUP", "TERM", "INT", "QUIT", "KILL", "TSTP", "USR1", "USR2", "STOP"};
|
// String[] sigs = new String[]{"HUP", "TERM", "INT", "QUIT", "KILL", "TSTP", "USR1", "USR2", "STOP"};
|
||||||
@@ -784,8 +833,15 @@ public final class Application {
|
|||||||
public static Application create(final boolean singleton) throws IOException {
|
public static Application create(final boolean singleton) throws IOException {
|
||||||
final String home = new File(System.getProperty(RESNAME_APP_HOME, "")).getCanonicalPath().replace('\\', '/');
|
final String home = new File(System.getProperty(RESNAME_APP_HOME, "")).getCanonicalPath().replace('\\', '/');
|
||||||
System.setProperty(RESNAME_APP_HOME, home);
|
System.setProperty(RESNAME_APP_HOME, home);
|
||||||
File appfile = new File(home, "conf/application.xml");
|
String confsubpath = System.getProperty(RESNAME_APP_CONF, "conf");
|
||||||
return new Application(singleton, load(new FileInputStream(appfile)));
|
File appfile;
|
||||||
|
if (confsubpath.charAt(0) == '/' || confsubpath.indexOf(':') > 0) {
|
||||||
|
appfile = new File(confsubpath).getCanonicalFile();
|
||||||
|
} else {
|
||||||
|
appfile = new File(new File(home), confsubpath);
|
||||||
|
}
|
||||||
|
File appconf = new File(appfile, "application.xml");
|
||||||
|
return new Application(singleton, load(new FileInputStream(appconf)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ package org.redkale.boot;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.Modifier;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
@@ -30,7 +30,7 @@ public final class ClassFilter<T> {
|
|||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ClassFilter.class.getName()); //日志对象
|
private static final Logger logger = Logger.getLogger(ClassFilter.class.getName()); //日志对象
|
||||||
|
|
||||||
private static final boolean finer = logger.isLoggable(Level.FINER); //日志级别
|
private static final boolean finest = logger.isLoggable(Level.FINEST); //日志级别
|
||||||
|
|
||||||
private final Set<FilterEntry<T>> entrys = new HashSet<>(); //符合条件的结果
|
private final Set<FilterEntry<T>> entrys = new HashSet<>(); //符合条件的结果
|
||||||
|
|
||||||
@@ -136,10 +136,11 @@ public final class ClassFilter<T> {
|
|||||||
*
|
*
|
||||||
* @param property AnyValue
|
* @param property AnyValue
|
||||||
* @param clazzname String
|
* @param clazzname String
|
||||||
|
* @param url URL
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final void filter(AnyValue property, String clazzname) {
|
public final void filter(AnyValue property, String clazzname, URL url) {
|
||||||
filter(property, clazzname, true);
|
filter(property, clazzname, true, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,6 +151,18 @@ public final class ClassFilter<T> {
|
|||||||
* @param autoscan 为true表示自动扫描的, false表示显著调用filter, AutoLoad的注解将被忽略
|
* @param autoscan 为true表示自动扫描的, false表示显著调用filter, AutoLoad的注解将被忽略
|
||||||
*/
|
*/
|
||||||
public final void filter(AnyValue property, String clazzname, boolean autoscan) {
|
public final void filter(AnyValue property, String clazzname, boolean autoscan) {
|
||||||
|
filter(property, clazzname, autoscan, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤指定的class
|
||||||
|
*
|
||||||
|
* @param property application.xml中对应class节点下的property属性项
|
||||||
|
* @param clazzname class名称
|
||||||
|
* @param autoscan 为true表示自动扫描的, false表示显著调用filter, AutoLoad的注解将被忽略
|
||||||
|
* @param url URL
|
||||||
|
*/
|
||||||
|
public final void filter(AnyValue property, String clazzname, boolean autoscan, URL url) {
|
||||||
boolean r = accept0(property, clazzname);
|
boolean r = accept0(property, clazzname);
|
||||||
ClassFilter cf = r ? this : null;
|
ClassFilter cf = r ? this : null;
|
||||||
if (r && ands != null) {
|
if (r && ands != null) {
|
||||||
@@ -165,7 +178,7 @@ public final class ClassFilter<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cf == null || clazzname.startsWith("sun.")) return;
|
if (cf == null || clazzname.startsWith("sun.") || clazzname.contains("module-info")) return;
|
||||||
try {
|
try {
|
||||||
Class clazz = classLoader.loadClass(clazzname);
|
Class clazz = classLoader.loadClass(clazzname);
|
||||||
if (!cf.accept(property, clazz, autoscan)) return;
|
if (!cf.accept(property, clazz, autoscan)) return;
|
||||||
@@ -189,9 +202,10 @@ public final class ClassFilter<T> {
|
|||||||
entrys.add(new FilterEntry(clazz, autoscan, false, property));
|
entrys.add(new FilterEntry(clazz, autoscan, false, property));
|
||||||
}
|
}
|
||||||
} catch (Throwable cfe) {
|
} catch (Throwable cfe) {
|
||||||
if (finer && !clazzname.startsWith("sun.") && !clazzname.startsWith("javax.")
|
if (finest && !clazzname.startsWith("sun.") && !clazzname.startsWith("javax.")
|
||||||
&& !clazzname.startsWith("com.sun.") && !clazzname.startsWith("jdk.")) {
|
&& !clazzname.startsWith("com.sun.") && !clazzname.startsWith("jdk.") && !clazzname.startsWith("META-INF")
|
||||||
logger.log(Level.FINEST, ClassFilter.class.getSimpleName() + " filter error", cfe);
|
&& (!(cfe instanceof NoClassDefFoundError) || (cfe instanceof UnsupportedClassVersionError) || ((NoClassDefFoundError) cfe).getMessage().startsWith("java.lang.NoClassDefFoundError: java"))) {
|
||||||
|
logger.log(Level.FINEST, ClassFilter.class.getSimpleName() + " filter error for class: " + clazzname + (url == null ? "" : (" in " + url)), cfe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,6 +361,7 @@ public final class ClassFilter<T> {
|
|||||||
|
|
||||||
public void setPrivilegeExcludes(Set<String> privilegeExcludes) {
|
public void setPrivilegeExcludes(Set<String> privilegeExcludes) {
|
||||||
this.privilegeExcludes = privilegeExcludes == null || privilegeExcludes.isEmpty() ? null : privilegeExcludes;
|
this.privilegeExcludes = privilegeExcludes == null || privilegeExcludes.isEmpty() ? null : privilegeExcludes;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -502,7 +517,7 @@ public final class ClassFilter<T> {
|
|||||||
classes.add(classname);
|
classes.add(classname);
|
||||||
if (debug) debugstr.append(classname).append("\r\n");
|
if (debug) debugstr.append(classname).append("\r\n");
|
||||||
for (final ClassFilter filter : filters) {
|
for (final ClassFilter filter : filters) {
|
||||||
if (filter != null) filter.filter(null, classname);
|
if (filter != null) filter.filter(null, classname, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -511,7 +526,7 @@ public final class ClassFilter<T> {
|
|||||||
} else {
|
} else {
|
||||||
for (String classname : classes) {
|
for (String classname : classes) {
|
||||||
for (final ClassFilter filter : filters) {
|
for (final ClassFilter filter : filters) {
|
||||||
if (filter != null) filter.filter(null, classname);
|
if (filter != null) filter.filter(null, classname, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -530,14 +545,14 @@ public final class ClassFilter<T> {
|
|||||||
classes.add(classname);
|
classes.add(classname);
|
||||||
if (debug) debugstr.append(classname).append("\r\n");
|
if (debug) debugstr.append(classname).append("\r\n");
|
||||||
for (final ClassFilter filter : filters) {
|
for (final ClassFilter filter : filters) {
|
||||||
if (filter != null) filter.filter(null, classname);
|
if (filter != null) filter.filter(null, classname, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cache.put(url, classes);
|
cache.put(url, classes);
|
||||||
} else {
|
} else {
|
||||||
for (String classname : classes) {
|
for (String classname : classes) {
|
||||||
for (final ClassFilter filter : filters) {
|
for (final ClassFilter filter : filters) {
|
||||||
if (filter != null) filter.filter(null, classname);
|
if (filter != null) filter.filter(null, classname, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -550,7 +565,9 @@ public final class ClassFilter<T> {
|
|||||||
files.add(root);
|
files.add(root);
|
||||||
} else if (root.isDirectory()) {
|
} else if (root.isDirectory()) {
|
||||||
if (exclude != null && exclude.equals(root)) return;
|
if (exclude != null && exclude.equals(root)) return;
|
||||||
for (File f : root.listFiles()) {
|
File[] lfs = root.listFiles();
|
||||||
|
if (lfs == null) throw new RuntimeException("File(" + root + ") cannot listFiles()");
|
||||||
|
for (File f : lfs) {
|
||||||
loadClassFiles(exclude, f, files);
|
loadClassFiles(exclude, f, files);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,7 +241,21 @@ public class LogFileHandler extends Handler {
|
|||||||
}
|
}
|
||||||
String limitstr = manager.getProperty(cname + ".limit");
|
String limitstr = manager.getProperty(cname + ".limit");
|
||||||
try {
|
try {
|
||||||
if (limitstr != null) this.limit = Math.abs(Integer.decode(limitstr));
|
if (limitstr != null) {
|
||||||
|
limitstr = limitstr.toUpperCase();
|
||||||
|
boolean g = limitstr.indexOf('G') > 0;
|
||||||
|
boolean m = limitstr.indexOf('M') > 0;
|
||||||
|
boolean k = limitstr.indexOf('K') > 0;
|
||||||
|
int ls = Math.abs(Integer.decode(limitstr.replace("G", "").replace("M", "").replace("K", "").replace("B", "")));
|
||||||
|
if (g) {
|
||||||
|
ls *= 1024 * 1024 * 1024;
|
||||||
|
} else if (m) {
|
||||||
|
ls *= 1024 * 1024;
|
||||||
|
} else if (k) {
|
||||||
|
ls *= 1024;
|
||||||
|
}
|
||||||
|
this.limit = ls;
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
String countstr = manager.getProperty(cname + ".count");
|
String countstr = manager.getProperty(cname + ".count");
|
||||||
@@ -266,7 +280,7 @@ public class LogFileHandler extends Handler {
|
|||||||
try {
|
try {
|
||||||
if (filterstr != null) {
|
if (filterstr != null) {
|
||||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(filterstr);
|
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(filterstr);
|
||||||
setFilter((Filter) clz.newInstance());
|
setFilter((Filter) clz.getDeclaredConstructor().newInstance());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
@@ -274,7 +288,7 @@ public class LogFileHandler extends Handler {
|
|||||||
try {
|
try {
|
||||||
if (formatterstr != null) {
|
if (formatterstr != null) {
|
||||||
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(formatterstr);
|
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(formatterstr);
|
||||||
setFormatter((Formatter) clz.newInstance());
|
setFormatter((Formatter) clz.getDeclaredConstructor().newInstance());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.lang.annotation.Annotation;
|
|||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.annotation.*;
|
import javax.annotation.*;
|
||||||
import static org.redkale.boot.Application.RESNAME_SNCP_ADDR;
|
import static org.redkale.boot.Application.RESNAME_SNCP_ADDR;
|
||||||
@@ -56,16 +57,19 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
protected ClassFilter<Service> createServiceClassFilter() {
|
protected ClassFilter<Service> createServiceClassFilter() {
|
||||||
return createClassFilter(this.sncpGroup, null, Service.class, new Class[]{org.redkale.watch.WatchService.class}, Annotation.class, "services", "service");
|
return createClassFilter(this.sncpGroup, null, Service.class, new Class[]{org.redkale.watch.WatchService.class}, Annotation.class, "services", "service");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
protected ClassFilter<Filter> createFilterClassFilter() {
|
protected ClassFilter<Filter> createFilterClassFilter() {
|
||||||
return createClassFilter(null, null, HttpFilter.class, new Class[]{WatchFilter.class}, null, "filters", "filter");
|
return createClassFilter(null, null, HttpFilter.class, new Class[]{WatchFilter.class}, null, "filters", "filter");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||||
return createClassFilter(null, WebServlet.class, HttpServlet.class, new Class[]{WatchServlet.class}, null, "servlets", "servlet");
|
return createClassFilter(null, WebServlet.class, HttpServlet.class, new Class[]{WatchServlet.class}, null, "servlets", "servlet");
|
||||||
}
|
}
|
||||||
@@ -87,6 +91,7 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter, ClassFilter otherFilter) throws Exception {
|
protected void loadServlet(ClassFilter<? extends Servlet> servletFilter, ClassFilter otherFilter) throws Exception {
|
||||||
if (httpServer != null) loadHttpServlet(servletFilter, otherFilter);
|
if (httpServer != null) loadHttpServlet(servletFilter, otherFilter);
|
||||||
}
|
}
|
||||||
@@ -119,8 +124,8 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
regFactory.register(resourceName, WebSocketNode.class, nodeService);
|
regFactory.register(resourceName, WebSocketNode.class, nodeService);
|
||||||
}
|
}
|
||||||
resourceFactory.inject(nodeService, self);
|
resourceFactory.inject(nodeService, self);
|
||||||
logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + nodeService);
|
|
||||||
field.set(src, nodeService);
|
field.set(src, nodeService);
|
||||||
|
logger.fine("[" + Thread.currentThread().getName() + "] Load Service " + nodeService);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.log(Level.SEVERE, "WebSocketNode inject error", e);
|
logger.log(Level.SEVERE, "WebSocketNode inject error", e);
|
||||||
@@ -136,7 +141,7 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
for (FilterEntry<? extends Filter> en : list) {
|
for (FilterEntry<? extends Filter> en : list) {
|
||||||
Class<HttpFilter> clazz = (Class<HttpFilter>) en.getType();
|
Class<HttpFilter> clazz = (Class<HttpFilter>) en.getType();
|
||||||
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
||||||
final HttpFilter filter = clazz.newInstance();
|
final HttpFilter filter = clazz.getDeclaredConstructor().newInstance();
|
||||||
resourceFactory.inject(filter, this);
|
resourceFactory.inject(filter, this);
|
||||||
DefaultAnyValue filterConf = (DefaultAnyValue) en.getProperty();
|
DefaultAnyValue filterConf = (DefaultAnyValue) en.getProperty();
|
||||||
this.httpServer.addHttpFilter(filter, filterConf);
|
this.httpServer.addHttpFilter(filter, filterConf);
|
||||||
@@ -172,7 +177,7 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
||||||
WebServlet ws = clazz.getAnnotation(WebServlet.class);
|
WebServlet ws = clazz.getAnnotation(WebServlet.class);
|
||||||
if (ws == null || ws.value().length == 0) continue;
|
if (ws == null || ws.value().length == 0) continue;
|
||||||
final HttpServlet servlet = clazz.newInstance();
|
final HttpServlet servlet = clazz.getDeclaredConstructor().newInstance();
|
||||||
resourceFactory.inject(servlet, this);
|
resourceFactory.inject(servlet, this);
|
||||||
final String[] mappings = ws.value();
|
final String[] mappings = ws.value();
|
||||||
String pref = ws.repair() ? prefix : "";
|
String pref = ws.repair() ? prefix : "";
|
||||||
@@ -213,6 +218,7 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
if (!rest) return;
|
if (!rest) return;
|
||||||
if (restConf == null) return; //不存在REST服务
|
if (restConf == null) return; //不存在REST服务
|
||||||
|
|
||||||
|
final long starts = System.currentTimeMillis();
|
||||||
String prefix0 = restConf.getValue("path", "");
|
String prefix0 = restConf.getValue("path", "");
|
||||||
if (!prefix0.isEmpty() && prefix0.charAt(prefix0.length() - 1) == '/') prefix0 = prefix0.substring(0, prefix0.length() - 1);
|
if (!prefix0.isEmpty() && prefix0.charAt(prefix0.length() - 1) == '/') prefix0 = prefix0.substring(0, prefix0.length() - 1);
|
||||||
if (!prefix0.isEmpty() && prefix0.charAt(0) != '/') prefix0 = '/' + prefix0;
|
if (!prefix0.isEmpty() && prefix0.charAt(0) != '/') prefix0 = '/' + prefix0;
|
||||||
@@ -239,35 +245,45 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
|
|
||||||
final ClassFilter restFilter = ClassFilter.create(null, restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
|
final ClassFilter restFilter = ClassFilter.create(null, restConf.getValue("includes", ""), restConf.getValue("excludes", ""), includeValues, excludeValues);
|
||||||
final boolean finest = logger.isLoggable(Level.FINEST);
|
final boolean finest = logger.isLoggable(Level.FINEST);
|
||||||
super.interceptorServices.forEach((service) -> {
|
final CountDownLatch scdl = new CountDownLatch(super.interceptorServices.size());
|
||||||
final Class stype = Sncp.getServiceType(service);
|
super.interceptorServices.stream().parallel().forEach((service) -> {
|
||||||
final String name = Sncp.getResourceName(service);
|
try {
|
||||||
RestService rs = (RestService) stype.getAnnotation(RestService.class);
|
final Class stype = Sncp.getServiceType(service);
|
||||||
if (rs == null || rs.ignore()) return;
|
final String name = Sncp.getResourceName(service);
|
||||||
|
RestService rs = (RestService) stype.getAnnotation(RestService.class);
|
||||||
|
if (rs == null || rs.ignore()) return;
|
||||||
|
|
||||||
final String stypename = stype.getName();
|
final String stypename = stype.getName();
|
||||||
if (!autoload && !includeValues.contains(stypename)) return;
|
if (!autoload && !includeValues.contains(stypename)) return;
|
||||||
if (!restFilter.accept(stypename)) return;
|
if (!restFilter.accept(stypename)) return;
|
||||||
if (restedObjects.contains(service)) {
|
synchronized (restedObjects) {
|
||||||
logger.log(Level.WARNING, stype.getName() + " repeat create rest servlet, so ignore");
|
if (restedObjects.contains(service)) {
|
||||||
return;
|
logger.log(Level.WARNING, stype.getName() + " repeat create rest servlet, so ignore");
|
||||||
}
|
return;
|
||||||
restedObjects.add(service); //避免重复创建Rest对象
|
}
|
||||||
HttpServlet servlet = httpServer.addRestServlet(serverClassLoader, service, userType, baseServletType, prefix);
|
restedObjects.add(service); //避免重复创建Rest对象
|
||||||
if (servlet == null) return; //没有HttpMapping方法的HttpServlet调用Rest.createRestServlet就会返回null
|
|
||||||
String prefix2 = prefix;
|
|
||||||
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
|
|
||||||
if (ws != null && !ws.repair()) prefix2 = "";
|
|
||||||
resourceFactory.inject(servlet, NodeHttpServer.this);
|
|
||||||
if (finest) logger.finest(threadName + " Create RestServlet(resource.name='" + name + "') = " + servlet);
|
|
||||||
if (ss != null) {
|
|
||||||
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
|
||||||
for (int i = 0; i < mappings.length; i++) {
|
|
||||||
mappings[i] = prefix2 + mappings[i];
|
|
||||||
}
|
}
|
||||||
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName(), mappings));
|
HttpServlet servlet = httpServer.addRestServlet(serverClassLoader, service, userType, baseServletType, prefix);
|
||||||
|
if (servlet == null) return; //没有HttpMapping方法的HttpServlet调用Rest.createRestServlet就会返回null
|
||||||
|
String prefix2 = prefix;
|
||||||
|
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
|
||||||
|
if (ws != null && !ws.repair()) prefix2 = "";
|
||||||
|
resourceFactory.inject(servlet, NodeHttpServer.this);
|
||||||
|
//if (finest) logger.finest(threadName + " Create RestServlet(resource.name='" + name + "') = " + servlet);
|
||||||
|
if (ss != null) {
|
||||||
|
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
||||||
|
for (int i = 0; i < mappings.length; i++) {
|
||||||
|
mappings[i] = prefix2 + mappings[i];
|
||||||
|
}
|
||||||
|
synchronized (ss) {
|
||||||
|
ss.add(new AbstractMap.SimpleEntry<>(servlet.getClass().getName() + "(rest.name='" + name + "')", mappings));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
scdl.countDown();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
scdl.await();
|
||||||
}
|
}
|
||||||
if (webSocketFilter != null) { //加载RestWebSocket
|
if (webSocketFilter != null) { //加载RestWebSocket
|
||||||
final Set<String> includeValues = new HashSet<>();
|
final Set<String> includeValues = new HashSet<>();
|
||||||
@@ -312,7 +328,7 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
|
WebServlet ws = servlet.getClass().getAnnotation(WebServlet.class);
|
||||||
if (ws != null && !ws.repair()) prefix2 = "";
|
if (ws != null && !ws.repair()) prefix2 = "";
|
||||||
resourceFactory.inject(servlet, NodeHttpServer.this);
|
resourceFactory.inject(servlet, NodeHttpServer.this);
|
||||||
if (finest) logger.finest(threadName + " " + stype.getName() + " create RestWebSocketServlet " + servlet);
|
if (finest) logger.finest(threadName + " " + stype.getName() + " create a RestWebSocketServlet");
|
||||||
if (ss != null) {
|
if (ss != null) {
|
||||||
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
String[] mappings = servlet.getClass().getAnnotation(WebServlet.class).value();
|
||||||
for (int i = 0; i < mappings.length; i++) {
|
for (int i = 0; i < mappings.length; i++) {
|
||||||
@@ -336,6 +352,7 @@ public class NodeHttpServer extends NodeServer {
|
|||||||
}
|
}
|
||||||
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
sb.append(" mapping to ").append(Arrays.toString(as.getValue())).append(LINE_SEPARATOR);
|
||||||
}
|
}
|
||||||
|
sb.append(threadName).append(" All HttpServlets load cost " + (System.currentTimeMillis() - starts) + " ms" + LINE_SEPARATOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import java.lang.reflect.*;
|
|||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.AbstractMap.SimpleEntry;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
@@ -19,10 +20,9 @@ import javax.annotation.*;
|
|||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
import static org.redkale.boot.Application.*;
|
import static org.redkale.boot.Application.*;
|
||||||
import org.redkale.boot.ClassFilter.FilterEntry;
|
import org.redkale.boot.ClassFilter.FilterEntry;
|
||||||
import org.redkale.convert.bson.*;
|
|
||||||
import org.redkale.net.Filter;
|
import org.redkale.net.Filter;
|
||||||
import org.redkale.net.*;
|
import org.redkale.net.*;
|
||||||
import org.redkale.net.http.WebSocketServlet;
|
import org.redkale.net.http.*;
|
||||||
import org.redkale.net.sncp.*;
|
import org.redkale.net.sncp.*;
|
||||||
import org.redkale.service.*;
|
import org.redkale.service.*;
|
||||||
import org.redkale.source.*;
|
import org.redkale.source.*;
|
||||||
@@ -96,6 +96,7 @@ public abstract class NodeServer {
|
|||||||
this.serverClassLoader = new RedkaleClassLoader(application.getServerClassLoader());
|
this.serverClassLoader = new RedkaleClassLoader(application.getServerClassLoader());
|
||||||
Thread.currentThread().setContextClassLoader(this.serverClassLoader);
|
Thread.currentThread().setContextClassLoader(this.serverClassLoader);
|
||||||
this.serverThread = Thread.currentThread();
|
this.serverThread = Thread.currentThread();
|
||||||
|
this.server.setServerClassLoader(serverClassLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends NodeServer> NodeServer create(Class<T> clazz, Application application, AnyValue serconf) {
|
public static <T extends NodeServer> NodeServer create(Class<T> clazz, Application application, AnyValue serconf) {
|
||||||
@@ -149,7 +150,7 @@ public abstract class NodeServer {
|
|||||||
String interceptorClass = this.serverConf.getValue("interceptor", "");
|
String interceptorClass = this.serverConf.getValue("interceptor", "");
|
||||||
if (!interceptorClass.isEmpty()) {
|
if (!interceptorClass.isEmpty()) {
|
||||||
Class clazz = serverClassLoader.loadClass(interceptorClass);
|
Class clazz = serverClassLoader.loadClass(interceptorClass);
|
||||||
this.interceptor = (NodeInterceptor) clazz.newInstance();
|
this.interceptor = (NodeInterceptor) clazz.getDeclaredConstructor().newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassFilter<Service> serviceFilter = createServiceClassFilter();
|
ClassFilter<Service> serviceFilter = createServiceClassFilter();
|
||||||
@@ -177,19 +178,27 @@ public abstract class NodeServer {
|
|||||||
final ResourceFactory appResFactory = application.getResourceFactory();
|
final ResourceFactory appResFactory = application.getResourceFactory();
|
||||||
final TransportFactory appSncpTranFactory = application.getSncpTransportFactory();
|
final TransportFactory appSncpTranFactory = application.getSncpTransportFactory();
|
||||||
final AnyValue resources = application.config.getAnyValue("resources");
|
final AnyValue resources = application.config.getAnyValue("resources");
|
||||||
final Map<String, AnyValue> cacheResource = new HashMap<>();
|
final Map<String, SimpleEntry<Class, AnyValue>> cacheResource = new HashMap<>();
|
||||||
final Map<String, AnyValue> dataResources = new HashMap<>();
|
final Map<String, SimpleEntry<Class, AnyValue>> dataResources = new HashMap<>();
|
||||||
if (resources != null) {
|
if (resources != null) {
|
||||||
for (AnyValue sourceConf : resources.getAnyValues("source")) {
|
for (AnyValue sourceConf : resources.getAnyValues("source")) {
|
||||||
try {
|
try {
|
||||||
Class type = serverClassLoader.loadClass(sourceConf.getValue("value"));
|
Class type = serverClassLoader.loadClass(sourceConf.getValue("value"));
|
||||||
if (type == DataSource.class) type = DataJdbcSource.class;
|
if (type == DataSource.class) {
|
||||||
|
type = DataMemorySource.class;
|
||||||
|
for (AnyValue itemConf : sourceConf.getAnyValues("property")) {
|
||||||
|
if (itemConf.getValue("name", "").contains(DataSources.JDBC_URL)) {
|
||||||
|
type = DataJdbcSource.class;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!Service.class.isAssignableFrom(type)) {
|
if (!Service.class.isAssignableFrom(type)) {
|
||||||
logger.log(Level.SEVERE, "load application source resource, but not Service error: " + sourceConf);
|
logger.log(Level.SEVERE, "load application source resource, but not Service error: " + sourceConf);
|
||||||
} else if (CacheSource.class.isAssignableFrom(type)) {
|
} else if (CacheSource.class.isAssignableFrom(type)) {
|
||||||
cacheResource.put(sourceConf.getValue("name", ""), sourceConf);
|
cacheResource.put(sourceConf.getValue("name", ""), new SimpleEntry(type, sourceConf));
|
||||||
} else if (DataSource.class.isAssignableFrom(type)) {
|
} else if (DataSource.class.isAssignableFrom(type)) {
|
||||||
dataResources.put(sourceConf.getValue("name", ""), sourceConf);
|
dataResources.put(sourceConf.getValue("name", ""), new SimpleEntry(type, sourceConf));
|
||||||
} else {
|
} else {
|
||||||
logger.log(Level.SEVERE, "load application source resource, but not CacheSource error: " + sourceConf);
|
logger.log(Level.SEVERE, "load application source resource, but not CacheSource error: " + sourceConf);
|
||||||
}
|
}
|
||||||
@@ -198,7 +207,7 @@ public abstract class NodeServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------- 注册Resource --------------------------------------------------------
|
//------------------------------------- 注册 Resource --------------------------------------------------------
|
||||||
resourceFactory.register((ResourceFactory rf, final Object src, String resourceName, Field field, final Object attachment) -> {
|
resourceFactory.register((ResourceFactory rf, final Object src, String resourceName, Field field, final Object attachment) -> {
|
||||||
try {
|
try {
|
||||||
Resource res = field.getAnnotation(Resource.class);
|
Resource res = field.getAnnotation(Resource.class);
|
||||||
@@ -221,24 +230,36 @@ public abstract class NodeServer {
|
|||||||
}
|
}
|
||||||
}, AnyValue.class, AnyValue[].class);
|
}, AnyValue.class, AnyValue[].class);
|
||||||
|
|
||||||
//------------------------------------- 注册DataSource --------------------------------------------------------
|
//------------------------------------- 注册 DataSource --------------------------------------------------------
|
||||||
resourceFactory.register((ResourceFactory rf, final Object src, String resourceName, Field field, final Object attachment) -> {
|
resourceFactory.register((ResourceFactory rf, final Object src, String resourceName, Field field, final Object attachment) -> {
|
||||||
try {
|
try {
|
||||||
if (field.getAnnotation(Resource.class) == null) return;
|
if (field.getAnnotation(Resource.class) == null) return;
|
||||||
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 DataSource
|
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不得注入 DataSource
|
||||||
AnyValue sourceConf = dataResources.get(resourceName);
|
SimpleEntry<Class, AnyValue> resEntry = dataResources.get(resourceName);
|
||||||
|
AnyValue sourceConf = resEntry == null ? null : resEntry.getValue();
|
||||||
DataSource source = null;
|
DataSource source = null;
|
||||||
boolean needinit = true;
|
boolean needinit = true;
|
||||||
if (sourceConf != null) {
|
if (sourceConf != null) {
|
||||||
final Class sourceType = serverClassLoader.loadClass(sourceConf.getValue("value"));
|
final Class sourceType = resEntry.getKey();
|
||||||
if (DataSource.class.isAssignableFrom(sourceType)) { // DataSource
|
if (sourceType == DataJdbcSource.class) {
|
||||||
final Service srcService = (Service) src;
|
source = DataSources.createDataSource(resourceName, sourceConf);
|
||||||
SncpClient client = Sncp.getSncpClient(srcService);
|
} else {
|
||||||
final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
|
boolean can = false;
|
||||||
final Set<String> groups = new HashSet<>();
|
for (Constructor cr : sourceType.getConstructors()) {
|
||||||
if (client != null && client.getSameGroup() != null) groups.add(client.getSameGroup());
|
if (cr.getParameterCount() == 0) {
|
||||||
if (client != null && client.getDiffGroups() != null) groups.addAll(client.getDiffGroups());
|
can = true;
|
||||||
source = (DataSource) Sncp.createLocalService(serverClassLoader, resourceName, sourceType, appResFactory, appSncpTranFactory, sncpAddr, groups, Sncp.getConf(srcService));
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (DataSource.class.isAssignableFrom(sourceType) && can) { // 必须有空构造函数
|
||||||
|
final Service srcService = (Service) src;
|
||||||
|
SncpClient client = Sncp.getSncpClient(srcService);
|
||||||
|
final InetSocketAddress sncpAddr = client == null ? null : client.getClientAddress();
|
||||||
|
final Set<String> groups = new HashSet<>();
|
||||||
|
if (client != null && client.getSameGroup() != null) groups.add(client.getSameGroup());
|
||||||
|
if (client != null && client.getDiffGroups() != null) groups.addAll(client.getDiffGroups());
|
||||||
|
source = (DataSource) Sncp.createLocalService(serverClassLoader, resourceName, sourceType, appResFactory, appSncpTranFactory, sncpAddr, groups, Sncp.getConf(srcService));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
@@ -271,11 +292,13 @@ public abstract class NodeServer {
|
|||||||
}
|
}
|
||||||
}, DataSource.class);
|
}, DataSource.class);
|
||||||
|
|
||||||
//------------------------------------- 注册CacheSource --------------------------------------------------------
|
//------------------------------------- 注册 CacheSource --------------------------------------------------------
|
||||||
resourceFactory.register(new ResourceFactory.ResourceLoader() {
|
resourceFactory.register(new ResourceFactory.ResourceLoader() {
|
||||||
|
@Override
|
||||||
public void load(ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) {
|
public void load(ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) {
|
||||||
try {
|
try {
|
||||||
if (field.getAnnotation(Resource.class) == null) return;
|
if (field.getAnnotation(Resource.class) == null) return;
|
||||||
|
if (!(src instanceof Service)) throw new RuntimeException("CacheSource must be inject in Service, cannot " + src);
|
||||||
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不需要注入 CacheSource
|
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不需要注入 CacheSource
|
||||||
final Service srcService = (Service) src;
|
final Service srcService = (Service) src;
|
||||||
SncpClient client = Sncp.getSncpClient(srcService);
|
SncpClient client = Sncp.getSncpClient(srcService);
|
||||||
@@ -284,8 +307,12 @@ public abstract class NodeServer {
|
|||||||
if (client != null && client.getSameGroup() != null) groups.add(client.getSameGroup());
|
if (client != null && client.getSameGroup() != null) groups.add(client.getSameGroup());
|
||||||
if (client != null && client.getDiffGroups() != null) groups.addAll(client.getDiffGroups());
|
if (client != null && client.getDiffGroups() != null) groups.addAll(client.getDiffGroups());
|
||||||
|
|
||||||
AnyValue sourceConf = cacheResource.get(resourceName);
|
SimpleEntry<Class, AnyValue> resEntry = cacheResource.get(resourceName);
|
||||||
if (sourceConf == null) sourceConf = dataResources.get(resourceName);
|
AnyValue sourceConf = resEntry == null ? null : resEntry.getValue();
|
||||||
|
if (sourceConf == null) {
|
||||||
|
SimpleEntry<Class, AnyValue> resEntry2 = dataResources.get(resourceName);
|
||||||
|
sourceConf = resEntry2 == null ? null : resEntry2.getValue();
|
||||||
|
}
|
||||||
final Class sourceType = sourceConf == null ? CacheMemorySource.class : serverClassLoader.loadClass(sourceConf.getValue("value"));
|
final Class sourceType = sourceConf == null ? CacheMemorySource.class : serverClassLoader.loadClass(sourceConf.getValue("value"));
|
||||||
Object source = null;
|
Object source = null;
|
||||||
if (CacheSource.class.isAssignableFrom(sourceType)) { // CacheSource
|
if (CacheSource.class.isAssignableFrom(sourceType)) { // CacheSource
|
||||||
@@ -317,15 +344,52 @@ public abstract class NodeServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean autoNone() {
|
public boolean autoNone() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}, CacheSource.class);
|
}, CacheSource.class);
|
||||||
|
|
||||||
|
//------------------------------------- 注册 WebSocketNode --------------------------------------------------------
|
||||||
|
resourceFactory.register(new ResourceFactory.ResourceLoader() {
|
||||||
|
@Override
|
||||||
|
public void load(ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) {
|
||||||
|
try {
|
||||||
|
if (field.getAnnotation(Resource.class) == null) return;
|
||||||
|
if ((src instanceof Service) && Sncp.isRemote((Service) src)) return; //远程模式不需要注入 WebSocketNode
|
||||||
|
Service nodeService = (Service) rf.find(resourceName, WebSocketNode.class);
|
||||||
|
if (nodeService == null) {
|
||||||
|
final HashSet<String> groups = new HashSet<>();
|
||||||
|
if (groups.isEmpty() && isSNCP() && NodeServer.this.sncpGroup != null) groups.add(NodeServer.this.sncpGroup);
|
||||||
|
nodeService = Sncp.createLocalService(serverClassLoader, resourceName, WebSocketNodeService.class, application.getResourceFactory(), application.getSncpTransportFactory(), NodeServer.this.sncpAddress, groups, (AnyValue) null);
|
||||||
|
(isSNCP() ? appResFactory : resourceFactory).register(resourceName, WebSocketNode.class, nodeService);
|
||||||
|
}
|
||||||
|
resourceFactory.inject(nodeService, self);
|
||||||
|
field.set(src, nodeService);
|
||||||
|
if (Sncp.isRemote(nodeService)) {
|
||||||
|
remoteServices.add(nodeService);
|
||||||
|
} else {
|
||||||
|
if (field != null) rf.inject(nodeService); //动态加载的Service也存在按需加载的注入资源
|
||||||
|
localServices.add(nodeService);
|
||||||
|
interceptorServices.add(nodeService);
|
||||||
|
if (consumer != null) consumer.accept(nodeService);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.SEVERE, "WebSocketNode inject error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean autoNone() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}, WebSocketNode.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void loadService(ClassFilter<? extends Service> serviceFilter, ClassFilter otherFilter) throws Exception {
|
protected void loadService(ClassFilter<? extends Service> serviceFilter, ClassFilter otherFilter) throws Exception {
|
||||||
if (serviceFilter == null) return;
|
if (serviceFilter == null) return;
|
||||||
|
final long starts = System.currentTimeMillis();
|
||||||
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
final String threadName = "[" + Thread.currentThread().getName() + "] ";
|
||||||
final Set<FilterEntry<? extends Service>> entrys = (Set) serviceFilter.getAllFilterEntrys();
|
final Set<FilterEntry<? extends Service>> entrys = (Set) serviceFilter.getAllFilterEntrys();
|
||||||
ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory;
|
ResourceFactory regFactory = isSNCP() ? application.getResourceFactory() : resourceFactory;
|
||||||
@@ -340,7 +404,6 @@ public abstract class NodeServer {
|
|||||||
if (DataSource.class.isAssignableFrom(serviceImplClass)) continue;
|
if (DataSource.class.isAssignableFrom(serviceImplClass)) continue;
|
||||||
if (CacheSource.class.isAssignableFrom(serviceImplClass)) continue;
|
if (CacheSource.class.isAssignableFrom(serviceImplClass)) continue;
|
||||||
if (DataCacheListener.class.isAssignableFrom(serviceImplClass)) continue;
|
if (DataCacheListener.class.isAssignableFrom(serviceImplClass)) continue;
|
||||||
//if (WebSocketNode.class.isAssignableFrom(serviceImplClass)) continue;
|
|
||||||
}
|
}
|
||||||
if (entry.getName().contains("$")) throw new RuntimeException("<name> value cannot contains '$' in " + entry.getProperty());
|
if (entry.getName().contains("$")) throw new RuntimeException("<name> value cannot contains '$' in " + entry.getProperty());
|
||||||
Service oldother = resourceFactory.find(entry.getName(), serviceImplClass);
|
Service oldother = resourceFactory.find(entry.getName(), serviceImplClass);
|
||||||
@@ -358,6 +421,11 @@ public abstract class NodeServer {
|
|||||||
if (localed && (serviceImplClass.isInterface() || Modifier.isAbstract(serviceImplClass.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
|
if (localed && (serviceImplClass.isInterface() || Modifier.isAbstract(serviceImplClass.getModifiers()))) continue; //本地模式不能实例化接口和抽象类的Service类
|
||||||
final ResourceFactory.ResourceLoader resourceLoader = (ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> {
|
final ResourceFactory.ResourceLoader resourceLoader = (ResourceFactory rf, final Object src, final String resourceName, Field field, final Object attachment) -> {
|
||||||
try {
|
try {
|
||||||
|
if (SncpClient.parseMethod(serviceImplClass).isEmpty() && serviceImplClass.getAnnotation(Priority.class) == null) { //class没有可用的方法且没有标记启动优先级的, 通常为BaseService
|
||||||
|
logger.log(Level.FINE, serviceImplClass + " cannot load because not found less one public non-final method");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Service service;
|
Service service;
|
||||||
boolean ws = src instanceof WebSocketServlet;
|
boolean ws = src instanceof WebSocketServlet;
|
||||||
if (ws || localed) { //本地模式
|
if (ws || localed) { //本地模式
|
||||||
@@ -365,8 +433,6 @@ public abstract class NodeServer {
|
|||||||
} else {
|
} else {
|
||||||
service = Sncp.createRemoteService(serverClassLoader, resourceName, serviceImplClass, appSncpTransFactory, NodeServer.this.sncpAddress, groups, entry.getProperty());
|
service = Sncp.createRemoteService(serverClassLoader, resourceName, serviceImplClass, appSncpTransFactory, NodeServer.this.sncpAddress, groups, entry.getProperty());
|
||||||
}
|
}
|
||||||
if (SncpClient.parseMethod(serviceImplClass).isEmpty() && serviceImplClass.getAnnotation(Priority.class) == null) return; //class没有可用的方法且没有标记启动优先级的, 通常为BaseService
|
|
||||||
|
|
||||||
final Class restype = Sncp.getResourceType(service);
|
final Class restype = Sncp.getResourceType(service);
|
||||||
if (rf.find(resourceName, restype) == null) {
|
if (rf.find(resourceName, restype) == null) {
|
||||||
regFactory.register(resourceName, restype, service);
|
regFactory.register(resourceName, restype, service);
|
||||||
@@ -430,24 +496,19 @@ public abstract class NodeServer {
|
|||||||
localServices.addAll(swlist);
|
localServices.addAll(swlist);
|
||||||
//this.loadPersistData();
|
//this.loadPersistData();
|
||||||
final List<String> slist = sb == null ? null : new CopyOnWriteArrayList<>();
|
final List<String> slist = sb == null ? null : new CopyOnWriteArrayList<>();
|
||||||
CountDownLatch clds = new CountDownLatch(localServices.size());
|
|
||||||
localServices.stream().forEach(y -> {
|
localServices.stream().forEach(y -> {
|
||||||
try {
|
long s = System.currentTimeMillis();
|
||||||
long s = System.currentTimeMillis();
|
y.init(Sncp.getConf(y));
|
||||||
y.init(Sncp.getConf(y));
|
long e = System.currentTimeMillis() - s;
|
||||||
long e = System.currentTimeMillis() - s;
|
String serstr = Sncp.toSimpleString(y, maxNameLength, maxClassNameLength);
|
||||||
String serstr = Sncp.toSimpleString(y, maxNameLength, maxClassNameLength);
|
if (slist != null) slist.add(new StringBuilder().append(threadName).append(serstr).append(" load and init in ").append(e).append(" ms").append(LINE_SEPARATOR).toString());
|
||||||
if (slist != null) slist.add(new StringBuilder().append(threadName).append(serstr).append(" load and init in ").append(e).append(" ms").append(LINE_SEPARATOR).toString());
|
|
||||||
} finally {
|
|
||||||
clds.countDown();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
clds.await();
|
|
||||||
if (slist != null && sb != null) {
|
if (slist != null && sb != null) {
|
||||||
List<String> wlist = new ArrayList<>(slist); //直接使用CopyOnWriteArrayList偶尔会出现莫名的异常(CopyOnWriteArrayList源码1185行)
|
List<String> wlist = new ArrayList<>(slist); //直接使用CopyOnWriteArrayList偶尔会出现莫名的异常(CopyOnWriteArrayList源码1185行)
|
||||||
for (String s : wlist) {
|
for (String s : wlist) {
|
||||||
sb.append(s);
|
sb.append(s);
|
||||||
}
|
}
|
||||||
|
sb.append(threadName).append("All Services load cost " + (System.currentTimeMillis() - starts) + " ms" + LINE_SEPARATOR);
|
||||||
}
|
}
|
||||||
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
if (sb != null && sb.length() > 0) logger.log(Level.INFO, sb.toString());
|
||||||
}
|
}
|
||||||
@@ -457,125 +518,6 @@ public abstract class NodeServer {
|
|||||||
maxClassNameLength = Math.max(maxClassNameLength, Sncp.getResourceType(y).getName().length() + 1);
|
maxClassNameLength = Math.max(maxClassNameLength, Sncp.getResourceType(y).getName().length() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//尚未完整实现, 先屏蔽, 单个Service在多个Server中存在的情况下进行缓存的方案还未考虑清楚
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void loadPersistData() throws Exception {
|
|
||||||
File home = application.getHome();
|
|
||||||
if (home == null || !home.isDirectory()) return;
|
|
||||||
File cachedir = new File(home, "cache");
|
|
||||||
if (!cachedir.isDirectory()) return;
|
|
||||||
int port = this.server.getSocketAddress().getPort();
|
|
||||||
final String prefix = "persist-" + port + "-";
|
|
||||||
final BsonConvert convert = BsonFactory.create().skipAllIgnore(true).getConvert();
|
|
||||||
synchronized (this.application) {
|
|
||||||
for (final File file : cachedir.listFiles((dir, name) -> name.startsWith(prefix))) {
|
|
||||||
if (!file.getName().endsWith(".bat")) continue;
|
|
||||||
String classAndResname = file.getName().substring(prefix.length(), file.getName().length() - 4); //去掉尾部的.bat
|
|
||||||
int pos = classAndResname.indexOf('-');
|
|
||||||
String servtype = pos > 0 ? classAndResname.substring(0, pos) : classAndResname;
|
|
||||||
String resname = pos > 0 ? classAndResname.substring(pos + 1) : "";
|
|
||||||
|
|
||||||
FileInputStream in = new FileInputStream(file);
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
||||||
int b;
|
|
||||||
while ((b = in.read()) != '\n') out.write(b);
|
|
||||||
final String[] fieldNames = out.toString().split(",");
|
|
||||||
int timeout = (int) ((System.currentTimeMillis() - file.lastModified()) / 1000);
|
|
||||||
for (final Service service : this.localServices) {
|
|
||||||
if (!servtype.equals(Sncp.getResourceType(service).getName())) continue;
|
|
||||||
if (!resname.equals(Sncp.getResourceName(service))) continue;
|
|
||||||
for (final String fieldName : fieldNames) {
|
|
||||||
Field field = null;
|
|
||||||
Class clzz = service.getClass();
|
|
||||||
do {
|
|
||||||
try {
|
|
||||||
field = clzz.getDeclaredField(fieldName);
|
|
||||||
break;
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
} while ((clzz = clzz.getSuperclass()) != Object.class);
|
|
||||||
field.setAccessible(true);
|
|
||||||
Object val = convert.convertFrom(field.getGenericType(), in);
|
|
||||||
Persist persist = field.getAnnotation(Persist.class);
|
|
||||||
if (persist.timeout() == 0 || persist.timeout() >= timeout) {
|
|
||||||
if (Modifier.isFinal(field.getModifiers())) {
|
|
||||||
if (Map.class.isAssignableFrom(field.getType())) {
|
|
||||||
((Map) field.get(service)).putAll((Map) val);
|
|
||||||
} else if (Collection.class.isAssignableFrom(field.getType())) {
|
|
||||||
((Collection) field.get(service)).addAll((Collection) val);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
field.set(service, val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (in.read() != '\n') logger.log(Level.SEVERE, servtype + "'s [" + resname + "] load value error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
in.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//尚未完整实现, 先屏蔽
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void savePersistData() throws IOException {
|
|
||||||
File home = application.getHome();
|
|
||||||
if (home == null || !home.isDirectory()) return;
|
|
||||||
File cachedir = new File(home, "cache");
|
|
||||||
int port = this.server.getSocketAddress().getPort();
|
|
||||||
final String prefix = "persist-" + port + "-";
|
|
||||||
final BsonConvert convert = BsonFactory.create().skipAllIgnore(true).getConvert();
|
|
||||||
for (final Service service : this.localServices) {
|
|
||||||
Class clzz = service.getClass();
|
|
||||||
final Set<String> fieldNameSet = new HashSet<>();
|
|
||||||
final List<Field> fields = new ArrayList<>();
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
do {
|
|
||||||
for (Field field : clzz.getDeclaredFields()) {
|
|
||||||
if (field.getAnnotation(Persist.class) == null) continue;
|
|
||||||
if (fieldNameSet.contains(field.getName())) continue;
|
|
||||||
if (Modifier.isStatic(field.getModifiers())) throw new RuntimeException(field + " cannot static on @" + Persist.class.getName() + " in " + clzz.getName());
|
|
||||||
if (Modifier.isFinal(field.getModifiers()) && !Map.class.isAssignableFrom(field.getType()) && !Collection.class.isAssignableFrom(field.getType())) {
|
|
||||||
throw new RuntimeException(field + " cannot final on @" + Persist.class.getName() + " in " + clzz.getName());
|
|
||||||
}
|
|
||||||
fieldNameSet.add(field.getName());
|
|
||||||
field.setAccessible(true);
|
|
||||||
try {
|
|
||||||
if (field.get(service) == null) continue;
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.log(Level.SEVERE, field + " get value error", e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
fields.add(field);
|
|
||||||
if (sb.length() > 0) sb.append(',');
|
|
||||||
sb.append(field.getName());
|
|
||||||
}
|
|
||||||
} while ((clzz = clzz.getSuperclass()) != Object.class);
|
|
||||||
|
|
||||||
if (fields.isEmpty()) continue; //没有数据需要缓存
|
|
||||||
// synchronized (this.application.localServices) {
|
|
||||||
// if (this.application.localServices.contains(service)) continue;
|
|
||||||
// this.application.localServices.add(service);
|
|
||||||
// }
|
|
||||||
if (!cachedir.isDirectory()) cachedir.mkdirs();
|
|
||||||
String resname = Sncp.getResourceName(service);
|
|
||||||
FileOutputStream out = new FileOutputStream(new File(cachedir, prefix + Sncp.getResourceType(service).getName() + (resname.isEmpty() ? "" : ("-" + resname)) + ".bat"));
|
|
||||||
out.write(sb.toString().getBytes());
|
|
||||||
out.write('\n');
|
|
||||||
for (Field field : fields) {
|
|
||||||
Object val = null;
|
|
||||||
try {
|
|
||||||
val = field.get(service);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.log(Level.SEVERE, field + " save value error", e);
|
|
||||||
}
|
|
||||||
convert.convertTo(out, field.getGenericType(), val);
|
|
||||||
out.write('\n');
|
|
||||||
}
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract ClassFilter<Filter> createFilterClassFilter();
|
protected abstract ClassFilter<Filter> createFilterClassFilter();
|
||||||
|
|
||||||
protected abstract ClassFilter<Servlet> createServletClassFilter();
|
protected abstract ClassFilter<Servlet> createServletClassFilter();
|
||||||
@@ -708,9 +650,12 @@ public abstract class NodeServer {
|
|||||||
public void shutdown() throws IOException {
|
public void shutdown() throws IOException {
|
||||||
if (interceptor != null) interceptor.preShutdown(this);
|
if (interceptor != null) interceptor.preShutdown(this);
|
||||||
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
final StringBuilder sb = logger.isLoggable(Level.INFO) ? new StringBuilder() : null;
|
||||||
|
final boolean finest = logger.isLoggable(Level.FINEST);
|
||||||
localServices.forEach(y -> {
|
localServices.forEach(y -> {
|
||||||
long s = System.currentTimeMillis();
|
long s = System.currentTimeMillis();
|
||||||
|
if (finest) logger.finest(y + " is destroying");
|
||||||
y.destroy(Sncp.getConf(y));
|
y.destroy(Sncp.getConf(y));
|
||||||
|
if (finest) logger.finest(y + " was destroyed");
|
||||||
long e = System.currentTimeMillis() - s;
|
long e = System.currentTimeMillis() - s;
|
||||||
if (e > 2 && sb != null) {
|
if (e > 2 && sb != null) {
|
||||||
sb.append(Sncp.toSimpleString(y, maxNameLength, maxClassNameLength)).append(" destroy ").append(e).append("ms").append(LINE_SEPARATOR);
|
sb.append(Sncp.toSimpleString(y, maxNameLength, maxClassNameLength)).append(" destroy ").append(e).append("ms").append(LINE_SEPARATOR);
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public class NodeSncpServer extends NodeServer {
|
|||||||
for (FilterEntry<? extends Filter> en : list) {
|
for (FilterEntry<? extends Filter> en : list) {
|
||||||
Class<SncpFilter> clazz = (Class<SncpFilter>) en.getType();
|
Class<SncpFilter> clazz = (Class<SncpFilter>) en.getType();
|
||||||
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
if (Modifier.isAbstract(clazz.getModifiers())) continue;
|
||||||
final SncpFilter filter = clazz.newInstance();
|
final SncpFilter filter = clazz.getDeclaredConstructor().newInstance();
|
||||||
resourceFactory.inject(filter, this);
|
resourceFactory.inject(filter, this);
|
||||||
DefaultAnyValue filterConf = (DefaultAnyValue) en.getProperty();
|
DefaultAnyValue filterConf = (DefaultAnyValue) en.getProperty();
|
||||||
this.sncpServer.addSncpFilter(filter, filterConf);
|
this.sncpServer.addSncpFilter(filter, filterConf);
|
||||||
|
|||||||
@@ -24,16 +24,19 @@ public class NodeWatchServer extends NodeHttpServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
protected ClassFilter<Service> createServiceClassFilter() {
|
protected ClassFilter<Service> createServiceClassFilter() {
|
||||||
return createClassFilter(this.sncpGroup, null, WatchService.class, null, Annotation.class, "services", "service");
|
return createClassFilter(this.sncpGroup, null, WatchService.class, null, Annotation.class, "services", "service");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
protected ClassFilter<Filter> createFilterClassFilter() {
|
protected ClassFilter<Filter> createFilterClassFilter() {
|
||||||
return createClassFilter(null, null, WatchFilter.class, null, null, "filters", "filter");
|
return createClassFilter(null, null, WatchFilter.class, null, null, "filters", "filter");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
protected ClassFilter<Servlet> createServletClassFilter() {
|
protected ClassFilter<Servlet> createServletClassFilter() {
|
||||||
return createClassFilter(null, WebServlet.class, WatchServlet.class, null, null, "servlets", "servlet");
|
return createClassFilter(null, WebServlet.class, WatchServlet.class, null, null, "servlets", "servlet");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
html.push(' <tr>');
|
html.push(' <tr>');
|
||||||
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
|
html.push('<td style="color:#ff00ff;">' + action.url + '</td>');
|
||||||
html.push('<td>' + action.comment + '</td>');
|
html.push('<td>' + action.comment + '</td>');
|
||||||
html.push('<td class="s">模块ID: ' + servlet.moduleid + '<br/>操作ID: ' + action.actionid + '<br/>需鉴权: ' + (action.auth ? '<font style="font-weight:bold;color:green;">true</font>' : '<font color=red>false</font>') + '</td>');
|
html.push('<td class="s" style="width:80px;">模块ID: ' + servlet.moduleid + '<br/>操作ID: ' + action.actionid + '<br/>需鉴权: ' + (action.auth ? '<font style="font-weight:bold;color:green;">true</font>' : '<font color=red>false</font>') + '</td>');
|
||||||
var paramshtml = [];
|
var paramshtml = [];
|
||||||
paramshtml.push('<table class="subtable">');
|
paramshtml.push('<table class="subtable">');
|
||||||
for (var p = 0; p < action.params.length; p++) {
|
for (var p = 0; p < action.params.length; p++) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.redkale.boot.watch;
|
package org.redkale.boot.watch;
|
||||||
|
|
||||||
import org.redkale.service.AbstractService;
|
import org.redkale.service.AbstractService;
|
||||||
|
import org.redkale.util.Comment;
|
||||||
import org.redkale.watch.WatchService;
|
import org.redkale.watch.WatchService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,4 +15,9 @@ import org.redkale.watch.WatchService;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractWatchService extends AbstractService implements WatchService {
|
public abstract class AbstractWatchService extends AbstractService implements WatchService {
|
||||||
|
|
||||||
|
@Comment("缺少参数")
|
||||||
|
public static final int RET_WATCH_PARAMS_ILLEGAL = 1600_0001;
|
||||||
|
|
||||||
|
@Comment("执行异常")
|
||||||
|
public static final int RET_WATCH_RUN_EXCEPTION = 1600_0002;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class FilterWatchService extends AbstractWatchService {
|
|||||||
public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005;
|
public static final int RET_FILTER_JAR_ILLEGAL = 1601_0005;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private Application application;
|
protected Application application;
|
||||||
|
|
||||||
@RestMapping(name = "addfilter", auth = false, comment = "动态增加Filter")
|
@RestMapping(name = "addfilter", auth = false, comment = "动态增加Filter")
|
||||||
public RetResult addFilter(@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar,
|
public RetResult addFilter(@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar,
|
||||||
@@ -47,4 +47,34 @@ public class FilterWatchService extends AbstractWatchService {
|
|||||||
}
|
}
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test1", auth = false, comment = "预留")
|
||||||
|
public RetResult test1() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test2", auth = false, comment = "预留")
|
||||||
|
public RetResult test2() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test3", auth = false, comment = "预留")
|
||||||
|
public RetResult test3() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test4", auth = false, comment = "预留")
|
||||||
|
public RetResult test4() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test5", auth = false, comment = "预留")
|
||||||
|
public RetResult test5() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test6", auth = false, comment = "预留")
|
||||||
|
public RetResult test6() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.boot.watch;
|
package org.redkale.boot.watch;
|
||||||
|
|
||||||
import org.redkale.net.http.RestService;
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import org.redkale.boot.*;
|
||||||
|
import org.redkale.net.Server;
|
||||||
|
import org.redkale.net.http.*;
|
||||||
|
import org.redkale.service.RetResult;
|
||||||
|
import org.redkale.util.Comment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -14,4 +23,83 @@ import org.redkale.net.http.RestService;
|
|||||||
@RestService(name = "server", catalog = "watch", repair = false)
|
@RestService(name = "server", catalog = "watch", repair = false)
|
||||||
public class ServerWatchService extends AbstractWatchService {
|
public class ServerWatchService extends AbstractWatchService {
|
||||||
|
|
||||||
|
@Comment("不存在的Server节点")
|
||||||
|
public static final int RET_SERVER_NOT_EXISTS = 1602_0001;
|
||||||
|
|
||||||
|
@Comment("更改Server监听地址端口失败")
|
||||||
|
public static final int RET_SERVER_CHANGEPORT_ERROR = 1602_0002;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected Application application;
|
||||||
|
|
||||||
|
@RestMapping(name = "info", comment = "单个Server信息查询")
|
||||||
|
public RetResult info(@RestParam(name = "#port:") final int port) {
|
||||||
|
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||||
|
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == port).findFirst().orElse(null);
|
||||||
|
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + port + ") not found");
|
||||||
|
return new RetResult(formatToMap(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "infos", comment = "Server信息查询")
|
||||||
|
public RetResult infos() {
|
||||||
|
Map<String, Object> rs = new LinkedHashMap<>();
|
||||||
|
for (NodeServer ns : application.getNodeServers()) {
|
||||||
|
Server server = ns.getServer();
|
||||||
|
rs.put("" + server.getSocketAddress().getPort(), formatToMap(ns));
|
||||||
|
}
|
||||||
|
return new RetResult(rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "changeaddress", comment = "更改Server的监听地址和端口")
|
||||||
|
public RetResult changeAddress(@RestParam(name = "#port:") final int oldport,
|
||||||
|
@RestParam(name = "#newhost:") final String newhost, @RestParam(name = "#newport:") final int newport) {
|
||||||
|
if (oldport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `oldport`");
|
||||||
|
if (newport < 1) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `newport`");
|
||||||
|
Stream<NodeServer> stream = application.getNodeServers().stream();
|
||||||
|
NodeServer node = stream.filter(ns -> ns.getServer().getSocketAddress().getPort() == oldport).findFirst().orElse(null);
|
||||||
|
if (node == null) return new RetResult(RET_SERVER_NOT_EXISTS, "Server(port=" + oldport + ") not found");
|
||||||
|
final Server server = node.getServer();
|
||||||
|
InetSocketAddress newAddr = new InetSocketAddress(newhost == null || newhost.isEmpty() ? server.getSocketAddress().getHostString() : newhost, newport);
|
||||||
|
try {
|
||||||
|
server.changeAddress(newAddr);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new RetResult(RET_SERVER_CHANGEPORT_ERROR, "changeaddress error");
|
||||||
|
}
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> formatToMap(NodeServer node) {
|
||||||
|
Server server = node.getServer();
|
||||||
|
Map<String, Object> rs = new LinkedHashMap<>();
|
||||||
|
String protocol = server.getProtocol();
|
||||||
|
if (node instanceof NodeSncpServer) {
|
||||||
|
protocol += "/SNCP";
|
||||||
|
} else if (node instanceof NodeWatchServer) {
|
||||||
|
protocol += "/WATCH";
|
||||||
|
} else if (node instanceof NodeHttpServer) {
|
||||||
|
protocol += "/HTTP";
|
||||||
|
} else {
|
||||||
|
NodeProtocol np = node.getClass().getAnnotation(NodeProtocol.class);
|
||||||
|
if (np != null && np.value().length > 0) protocol += "/" + np.value()[0];
|
||||||
|
}
|
||||||
|
rs.put("name", server.getName());
|
||||||
|
rs.put("protocol", protocol);
|
||||||
|
rs.put("address", server.getSocketAddress());
|
||||||
|
rs.put("threads", server.getThreads());
|
||||||
|
rs.put("backlog", server.getBacklog());
|
||||||
|
rs.put("bufferCapacity", server.getBufferCapacity());
|
||||||
|
rs.put("bufferPoolSize", server.getBufferPoolSize());
|
||||||
|
rs.put("charset", server.getCharset() == null ? "UTF-8" : server.getCharset().name());
|
||||||
|
rs.put("maxbody", server.getMaxbody());
|
||||||
|
rs.put("maxconns", server.getMaxconns());
|
||||||
|
rs.put("serverStartTime", server.getServerStartTime());
|
||||||
|
rs.put("responsePoolSize", server.getResponsePoolSize());
|
||||||
|
rs.put("readTimeoutSeconds", server.getReadTimeoutSeconds());
|
||||||
|
rs.put("writeTimeoutSeconds", server.getWriteTimeoutSeconds());
|
||||||
|
rs.put("createConnectionCount", server.getCreateConnectionCount());
|
||||||
|
rs.put("livingConnectionCount", server.getLivingConnectionCount());
|
||||||
|
rs.put("closedConnectionCount", server.getClosedConnectionCount());
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.boot.watch;
|
package org.redkale.boot.watch;
|
||||||
|
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.util.*;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import org.redkale.boot.Application;
|
import org.redkale.boot.*;
|
||||||
import org.redkale.net.TransportFactory;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
import org.redkale.net.http.*;
|
import org.redkale.net.http.*;
|
||||||
|
import org.redkale.service.RetResult;
|
||||||
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -19,21 +23,177 @@ import org.redkale.net.http.*;
|
|||||||
@RestService(name = "service", catalog = "watch", repair = false)
|
@RestService(name = "service", catalog = "watch", repair = false)
|
||||||
public class ServiceWatchService extends AbstractWatchService {
|
public class ServiceWatchService extends AbstractWatchService {
|
||||||
|
|
||||||
@Resource
|
@Comment("没有找到目标Service")
|
||||||
private Application application;
|
public static final int RET_SERVICE_DEST_NOT_EXISTS = 1603_0001;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private TransportFactory transportFactory;
|
protected Application application;
|
||||||
|
|
||||||
// @RestMapping(name = "load", auth = false, comment = "动态增加Service")
|
@RestConvert(type = void.class)
|
||||||
// public RetResult loadService(String type, @RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
@RestMapping(name = "setfield", auth = false, comment = "设置Service中指定字段的内容")
|
||||||
// //待开发
|
public RetResult setfield(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
// return RetResult.success();
|
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||||
// }
|
@RestParam(name = "field", comment = "字段名") String field,
|
||||||
//
|
@RestParam(name = "value", comment = "字段值") String value) {
|
||||||
// @RestMapping(name = "stop", auth = false, comment = "动态停止Service")
|
if (name == null) name = "";
|
||||||
// public RetResult stopService(String name, String type) {
|
if (type == null) type = "";
|
||||||
// //待开发
|
if (field == null) field = "";
|
||||||
// return RetResult.success();
|
type = type.trim();
|
||||||
// }
|
field = field.trim();
|
||||||
|
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||||
|
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
||||||
|
Object dest = findService(name, type);
|
||||||
|
Class clazz = dest.getClass();
|
||||||
|
Throwable t = null;
|
||||||
|
try {
|
||||||
|
Field fieldObj = null;
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
fieldObj = clazz.getDeclaredField(field);
|
||||||
|
break;
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (t == null) t = e;
|
||||||
|
}
|
||||||
|
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||||
|
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
|
||||||
|
fieldObj.setAccessible(true);
|
||||||
|
fieldObj.set(dest, JsonConvert.root().convertFrom(fieldObj.getGenericType(), value));
|
||||||
|
return RetResult.success();
|
||||||
|
} catch (Throwable t2) {
|
||||||
|
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestConvert(type = void.class)
|
||||||
|
@RestMapping(name = "getfield", auth = false, comment = "查询Service中指定字段的内容")
|
||||||
|
public RetResult getfield(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
|
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||||
|
@RestParam(name = "field", comment = "字段名") String field) {
|
||||||
|
if (name == null) name = "";
|
||||||
|
if (type == null) type = "";
|
||||||
|
if (field == null) field = "";
|
||||||
|
type = type.trim();
|
||||||
|
field = field.trim();
|
||||||
|
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||||
|
if (field.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `field`");
|
||||||
|
Object dest = findService(name, type);
|
||||||
|
Class clazz = dest.getClass();
|
||||||
|
Throwable t = null;
|
||||||
|
try {
|
||||||
|
Field fieldObj = null;
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
fieldObj = clazz.getDeclaredField(field);
|
||||||
|
break;
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (t == null) t = e;
|
||||||
|
}
|
||||||
|
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||||
|
if (fieldObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + String.valueOf(t) + ")");
|
||||||
|
fieldObj.setAccessible(true);
|
||||||
|
return new RetResult(fieldObj.get(dest));
|
||||||
|
} catch (Throwable t2) {
|
||||||
|
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestConvert(type = void.class)
|
||||||
|
@RestMapping(name = "runmethod", auth = false, comment = "调用Service中指定方法")
|
||||||
|
public RetResult runmethod(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
|
@RestParam(name = "type", comment = "Service的类名") String type,
|
||||||
|
@RestParam(name = "method", comment = "Service的方法名") String method,
|
||||||
|
@RestParam(name = "params", comment = "方法的参数值") List<String> params,
|
||||||
|
@RestParam(name = "paramtypes", comment = "方法的参数数据类型") List<String> paramtypes) {
|
||||||
|
if (name == null) name = "";
|
||||||
|
if (type == null) type = "";
|
||||||
|
if (method == null) method = "";
|
||||||
|
type = type.trim();
|
||||||
|
method = method.trim();
|
||||||
|
if (type.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `type`");
|
||||||
|
if (method.isEmpty()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param `method`");
|
||||||
|
Object dest = findService(name, type);
|
||||||
|
Class clazz = dest.getClass();
|
||||||
|
Throwable t = null;
|
||||||
|
final int paramcount = params == null ? 0 : params.size();
|
||||||
|
if (paramtypes != null && paramcount != paramtypes.size()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "params.size not equals to paramtypes.size");
|
||||||
|
try {
|
||||||
|
Method methodObj = null;
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
for (Method m : clazz.getDeclaredMethods()) {
|
||||||
|
if (m.getName().equals(method) && m.getParameterCount() == paramcount) {
|
||||||
|
boolean flag = true;
|
||||||
|
if (paramtypes != null) {
|
||||||
|
Class[] pts = m.getParameterTypes();
|
||||||
|
for (int i = 0; i < pts.length; i++) {
|
||||||
|
if (!pts[i].getName().endsWith(paramtypes.get(i))) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flag) {
|
||||||
|
methodObj = m;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (methodObj != null) break;
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (t == null) t = e;
|
||||||
|
}
|
||||||
|
} while ((clazz = clazz.getSuperclass()) != Object.class);
|
||||||
|
if (methodObj == null) return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + (t == null ? ("not found method(" + method + ")") : String.valueOf(t)) + ")");
|
||||||
|
methodObj.setAccessible(true);
|
||||||
|
if (paramcount < 1) return new RetResult(methodObj.invoke(dest));
|
||||||
|
Object[] paramObjs = new Object[paramcount];
|
||||||
|
Type[] pts = methodObj.getGenericParameterTypes();
|
||||||
|
for (int i = 0; i < paramObjs.length; i++) {
|
||||||
|
paramObjs[i] = JsonConvert.root().convertFrom(pts[i], params.get(i));
|
||||||
|
}
|
||||||
|
return new RetResult(methodObj.invoke(dest, paramObjs));
|
||||||
|
} catch (Throwable t2) {
|
||||||
|
return new RetResult(RET_WATCH_RUN_EXCEPTION, "run exception (" + t2.toString() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object findService(String name, String type) {
|
||||||
|
Object dest = null;
|
||||||
|
for (NodeServer ns : application.getNodeServers()) {
|
||||||
|
ResourceFactory resFactory = ns.getResourceFactory();
|
||||||
|
List list = resFactory.query((n, s) -> name.equals(n) && s != null && s.getClass().getName().endsWith(type));
|
||||||
|
if (list == null || list.isEmpty()) continue;
|
||||||
|
dest = list.get(0);
|
||||||
|
}
|
||||||
|
if (dest == null) return new RetResult(RET_SERVICE_DEST_NOT_EXISTS, "not found servie (name=" + name + ", type=" + type + ")");
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "load", auth = false, comment = "动态增加Service")
|
||||||
|
public RetResult loadService(@RestParam(name = "type", comment = "Service的类名") String type,
|
||||||
|
@RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
||||||
|
//待开发
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "reload", auth = false, comment = "重新加载Service")
|
||||||
|
public RetResult reloadService(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
|
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||||
|
//待开发
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "stop", auth = false, comment = "动态停止Service")
|
||||||
|
public RetResult stopService(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
|
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||||
|
//待开发
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "find", auth = false, comment = "查找Service")
|
||||||
|
public RetResult find(@RestParam(name = "name", comment = "Service的资源名") String name,
|
||||||
|
@RestParam(name = "type", comment = "Service的类名") String type) {
|
||||||
|
//待开发
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ import org.redkale.net.http.*;
|
|||||||
public class ServletWatchService extends AbstractWatchService {
|
public class ServletWatchService extends AbstractWatchService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private Application application;
|
protected Application application;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private TransportFactory transportFactory;
|
protected TransportFactory transportFactory;
|
||||||
//
|
//
|
||||||
// @RestMapping(name = "load", auth = false, comment = "动态增加Servlet")
|
// @RestMapping(name = "load", auth = false, comment = "动态增加Servlet")
|
||||||
// public RetResult loadServlet(String type, @RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
// public RetResult loadServlet(String type, @RestUploadFile(maxLength = 10 * 1024 * 1024, fileNameReg = "\\.jar$") byte[] jar) {
|
||||||
|
|||||||
@@ -5,22 +5,118 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.boot.watch;
|
package org.redkale.boot.watch;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import org.redkale.boot.Application;
|
import org.redkale.boot.Application;
|
||||||
import org.redkale.net.TransportFactory;
|
import org.redkale.net.http.*;
|
||||||
import org.redkale.net.http.RestService;
|
import org.redkale.service.*;
|
||||||
|
import org.redkale.source.*;
|
||||||
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* WATCH服务, 操作DataSource源
|
||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
@RestService(name = "source", catalog = "watch", repair = false)
|
@RestService(name = "source", catalog = "watch", repair = false)
|
||||||
public class SourceWatchService extends AbstractWatchService {
|
public class SourceWatchService extends AbstractWatchService {
|
||||||
|
|
||||||
@Resource
|
@Comment("不存在的Source")
|
||||||
private Application application;
|
public static final int RET_SOURCE_NOT_EXISTS = 1605_0001;
|
||||||
|
|
||||||
|
@Comment("Source不支持getReadPoolSource/getWritePoolSource方法")
|
||||||
|
public static final int RET_SOURCE_CHANGE_METHOD_NOT_EXISTS = 1605_0002;
|
||||||
|
|
||||||
|
@Comment("PoolSource调用change方法失败")
|
||||||
|
public static final int RET_SOURCE_METHOD_INVOKE_NOT_EXISTS = 1605_0003;
|
||||||
|
|
||||||
|
@Resource(name = "APP_HOME")
|
||||||
|
protected File home;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private TransportFactory transportFactory;
|
protected Application application;
|
||||||
|
|
||||||
|
@RestMapping(name = "change", auth = false, comment = "动态更改DataSource的配置")
|
||||||
|
public RetResult addNode(@RestParam(name = "name", comment = "DataSource的标识") final String name,
|
||||||
|
@RestParam(name = "properties", comment = "配置") Properties properties,
|
||||||
|
@RestParam(name = "xmlpath", comment = "配置文件路径") String xmlpath) throws IOException {
|
||||||
|
if (name == null) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param (name)");
|
||||||
|
if (properties == null && xmlpath != null) {
|
||||||
|
File f = new File(xmlpath);
|
||||||
|
if (!f.isFile()) f = new File(home, xmlpath);
|
||||||
|
if (!f.isFile()) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found file (" + xmlpath + ")");
|
||||||
|
FileInputStream in = new FileInputStream(f);
|
||||||
|
Map<String, Properties> map = DataSources.loadPersistenceXml(in);
|
||||||
|
properties = map.get(name);
|
||||||
|
}
|
||||||
|
if (properties == null) return new RetResult(RET_WATCH_PARAMS_ILLEGAL, "not found param (properties)");
|
||||||
|
DataSource source = null;
|
||||||
|
for (DataSource s : application.getDataSources()) {
|
||||||
|
String resName = ((Resourcable) s).resourceName();
|
||||||
|
if (resName == null) continue;
|
||||||
|
if (!resName.equals(name)) continue;
|
||||||
|
source = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (source == null) return new RetResult(RET_SOURCE_NOT_EXISTS, "not found source (name = " + name + ")");
|
||||||
|
Method readPoolMethod = null;
|
||||||
|
Method writePoolMethod = null;
|
||||||
|
Class stype = source.getClass();
|
||||||
|
do {
|
||||||
|
for (Method m : stype.getDeclaredMethods()) {
|
||||||
|
if (!PoolSource.class.isAssignableFrom(m.getReturnType())) continue;
|
||||||
|
if (m.getParameterCount() != 0) continue;
|
||||||
|
if (m.getName().equals("getReadPoolSource")) {
|
||||||
|
readPoolMethod = m;
|
||||||
|
} else if (m.getName().equals("getWritePoolSource")) {
|
||||||
|
writePoolMethod = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ((stype = stype.getSuperclass()) != Object.class);
|
||||||
|
if (readPoolMethod == null) return new RetResult(RET_SOURCE_CHANGE_METHOD_NOT_EXISTS, "not found source method(getReadPoolSource)");
|
||||||
|
if (writePoolMethod == null) return new RetResult(RET_SOURCE_CHANGE_METHOD_NOT_EXISTS, "not found source method(getWritePoolSource)");
|
||||||
|
readPoolMethod.setAccessible(true);
|
||||||
|
writePoolMethod.setAccessible(true);
|
||||||
|
try {
|
||||||
|
PoolSource readPoolSource = (PoolSource) readPoolMethod.invoke(source);
|
||||||
|
PoolSource writePoolSource = (PoolSource) writePoolMethod.invoke(source);
|
||||||
|
readPoolSource.change(properties);
|
||||||
|
writePoolSource.change(properties);
|
||||||
|
return RetResult.success();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return new RetResult(RET_SOURCE_METHOD_INVOKE_NOT_EXISTS, "poolsource invoke method('change') error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test1", auth = false, comment = "预留")
|
||||||
|
public RetResult test1() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test2", auth = false, comment = "预留")
|
||||||
|
public RetResult test2() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test3", auth = false, comment = "预留")
|
||||||
|
public RetResult test3() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test4", auth = false, comment = "预留")
|
||||||
|
public RetResult test4() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test5", auth = false, comment = "预留")
|
||||||
|
public RetResult test5() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test6", auth = false, comment = "预留")
|
||||||
|
public RetResult test6() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ public class TransportWatchService extends AbstractWatchService {
|
|||||||
public static final int RET_TRANSPORT_ADDR_EXISTS = 1606_0003;
|
public static final int RET_TRANSPORT_ADDR_EXISTS = 1606_0003;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private Application application;
|
protected Application application;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private TransportFactory transportFactory;
|
protected TransportFactory transportFactory;
|
||||||
|
|
||||||
@RestMapping(name = "listnodes", auth = false, comment = "获取所有Node节点")
|
@RestMapping(name = "listnodes", auth = false, comment = "获取所有Node节点")
|
||||||
public List<TransportGroupInfo> listNodes() {
|
public List<TransportGroupInfo> listNodes() {
|
||||||
@@ -135,4 +135,24 @@ public class TransportWatchService extends AbstractWatchService {
|
|||||||
}
|
}
|
||||||
return RetResult.success();
|
return RetResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test1", auth = false, comment = "预留")
|
||||||
|
public RetResult test1() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test2", auth = false, comment = "预留")
|
||||||
|
public RetResult test2() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test3", auth = false, comment = "预留")
|
||||||
|
public RetResult test3() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RestMapping(name = "test4", auth = false, comment = "预留")
|
||||||
|
public RetResult test4() {
|
||||||
|
return RetResult.success();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,16 +42,17 @@ public final class AnyEncoder<T> implements Encodeable<Writer, T> {
|
|||||||
out.writeNull();
|
out.writeNull();
|
||||||
} else {
|
} else {
|
||||||
int count = values.length - values.length % 2;
|
int count = values.length - values.length % 2;
|
||||||
out.writeMapB(count / 2);
|
if (out.writeMapB(count / 2, (Encodeable) this, (Encodeable) this, values) < 0) {
|
||||||
for (int i = 0; i < count; i += 2) {
|
for (int i = 0; i < count; i += 2) {
|
||||||
if (i > 0) out.writeArrayMark();
|
if (i > 0) out.writeArrayMark();
|
||||||
this.convertTo(out, (T) values[i]);
|
this.convertTo(out, (T) values[i]);
|
||||||
out.writeMapMark();
|
out.writeMapMark();
|
||||||
Object val = values[i + 1];
|
Object val = values[i + 1];
|
||||||
if (val instanceof CompletableFuture) {
|
if (val instanceof CompletableFuture) {
|
||||||
this.convertTo(out, (T) ((CompletableFuture) val).join());
|
this.convertTo(out, (T) ((CompletableFuture) val).join());
|
||||||
} else {
|
} else {
|
||||||
this.convertTo(out, (T) val);
|
this.convertTo(out, (T) val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.writeMapE();
|
out.writeMapE();
|
||||||
|
|||||||
@@ -20,19 +20,19 @@ import java.util.*;
|
|||||||
* @param <T> 反解析的数组元素类型
|
* @param <T> 反解析的数组元素类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
public class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
||||||
|
|
||||||
private final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
private final Type componentType;
|
protected final Type componentType;
|
||||||
|
|
||||||
private final Class componentClass;
|
protected final Class componentClass;
|
||||||
|
|
||||||
protected final Decodeable<Reader, T> decoder;
|
protected final Decodeable<Reader, T> componentDecoder;
|
||||||
|
|
||||||
private boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public ArrayDecoder(final ConvertFactory factory, final Type type) {
|
public ArrayDecoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -51,7 +51,7 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
|||||||
this.componentClass = (Class) this.componentType;
|
this.componentClass = (Class) this.componentType;
|
||||||
}
|
}
|
||||||
factory.register(type, this);
|
factory.register(type, this);
|
||||||
this.decoder = factory.loadDecoder(this.componentType);
|
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||||
} finally {
|
} finally {
|
||||||
inited = true;
|
inited = true;
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
@@ -62,9 +62,19 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T[] convertFrom(Reader in) {
|
public T[] convertFrom(Reader in) {
|
||||||
final int len = in.readArrayB();
|
return convertFrom(in, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T[] convertFrom(Reader in, DeMember member) {
|
||||||
|
byte[] typevals = new byte[1];
|
||||||
|
int len = in.readArrayB(member, typevals, componentDecoder);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
if (this.decoder == null) {
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(member, componentDecoder);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
|
if (this.componentDecoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
@@ -75,11 +85,16 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Decodeable<Reader, T> localdecoder = this.decoder;
|
final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
|
||||||
final List<T> result = new ArrayList();
|
final List<T> result = new ArrayList();
|
||||||
|
boolean first = true;
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
result.add(localdecoder.convertFrom(in));
|
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||||
|
Reader itemReader = getItemReader(in, member, first);
|
||||||
|
if (itemReader == null) break;
|
||||||
|
result.add(readMemberValue(itemReader, member, localdecoder, first));
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
@@ -91,9 +106,25 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
|||||||
return result.toArray(rs);
|
return result.toArray(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||||
|
return in.hasNext(startPosition, contentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
|
||||||
|
return decoder.convertFrom(in);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:" + this.decoder + "}";
|
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:" + this.componentDecoder + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -101,4 +132,12 @@ public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type getComponentType() {
|
||||||
|
return componentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Decodeable<Reader, T> getComponentDecoder() {
|
||||||
|
return componentDecoder;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,19 +19,19 @@ import java.lang.reflect.*;
|
|||||||
* @param <T> 序列化的数组元素类型
|
* @param <T> 序列化的数组元素类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
public class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
||||||
|
|
||||||
private final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
private final Type componentType;
|
protected final Type componentType;
|
||||||
|
|
||||||
private final Encodeable anyEncoder;
|
protected final Encodeable anyEncoder;
|
||||||
|
|
||||||
private final Encodeable<Writer, Object> encoder;
|
protected final Encodeable<Writer, Object> componentEncoder;
|
||||||
|
|
||||||
private boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public ArrayEncoder(final ConvertFactory factory, final Type type) {
|
public ArrayEncoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -45,7 +45,7 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
|||||||
throw new ConvertException("(" + type + ") is not a array type");
|
throw new ConvertException("(" + type + ") is not a array type");
|
||||||
}
|
}
|
||||||
factory.register(type, this);
|
factory.register(type, this);
|
||||||
this.encoder = factory.loadEncoder(this.componentType);
|
this.componentEncoder = factory.loadEncoder(this.componentType);
|
||||||
this.anyEncoder = factory.getAnyEncoder();
|
this.anyEncoder = factory.getAnyEncoder();
|
||||||
} finally {
|
} finally {
|
||||||
inited = true;
|
inited = true;
|
||||||
@@ -57,16 +57,20 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void convertTo(Writer out, T[] value) {
|
public void convertTo(Writer out, T[] value) {
|
||||||
|
convertTo(out, null, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertTo(Writer out, EnMember member, T[] value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value.length == 0) {
|
if (value.length == 0) {
|
||||||
out.writeArrayB(0);
|
out.writeArrayB(0, componentEncoder, value);
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.encoder == null) {
|
if (this.componentEncoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
@@ -77,24 +81,38 @@ public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayB(value.length);
|
if (out.writeArrayB(value.length, componentEncoder, value) < 0) {
|
||||||
final Type comp = this.componentType;
|
final Type comp = this.componentType;
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (Object v : value) {
|
for (Object v : value) {
|
||||||
if (!first) out.writeArrayMark();
|
if (!first) out.writeArrayMark();
|
||||||
((v != null && v.getClass() == comp) ? encoder : anyEncoder).convertTo(out, v);
|
writeMemberValue(out, member, ((v != null && (v.getClass() == comp || out.specify() == comp)) ? componentEncoder : anyEncoder), v, first);
|
||||||
if (first) first = false;
|
if (first) first = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void writeMemberValue(Writer out, EnMember member, Encodeable<Writer, Object> encoder, Object value, boolean first) {
|
||||||
|
encoder.convertTo(out, value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.encoder + "}";
|
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.componentEncoder + "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type getComponentType() {
|
||||||
|
return componentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Encodeable<Writer, Object> getComponentEncoder() {
|
||||||
|
return componentEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,19 +21,19 @@ import java.util.Collection;
|
|||||||
* @param <T> 反解析的集合元素类型
|
* @param <T> 反解析的集合元素类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class CollectionDecoder<T> implements Decodeable<Reader, Collection<T>> {
|
public class CollectionDecoder<T> implements Decodeable<Reader, Collection<T>> {
|
||||||
|
|
||||||
private final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
private final Type componentType;
|
protected final Type componentType;
|
||||||
|
|
||||||
protected Creator<Collection<T>> creator;
|
protected Creator<Collection<T>> creator;
|
||||||
|
|
||||||
protected final Decodeable<Reader, T> decoder;
|
protected final Decodeable<Reader, T> componentDecoder;
|
||||||
|
|
||||||
private boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public CollectionDecoder(final ConvertFactory factory, final Type type) {
|
public CollectionDecoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -43,12 +43,12 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
|
|||||||
this.componentType = pt.getActualTypeArguments()[0];
|
this.componentType = pt.getActualTypeArguments()[0];
|
||||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||||
factory.register(type, this);
|
factory.register(type, this);
|
||||||
this.decoder = factory.loadDecoder(this.componentType);
|
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||||
} else if(factory.isReversible()){
|
} else if (factory.isReversible()) {
|
||||||
this.componentType = Object.class;
|
this.componentType = Object.class;
|
||||||
this.creator = factory.loadCreator(Object.class);
|
this.creator = factory.loadCreator(type instanceof Class ? (Class) type : Collection.class);
|
||||||
factory.register(type, this);
|
factory.register(type, this);
|
||||||
this.decoder = factory.loadDecoder(this.componentType);
|
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||||
} else {
|
} else {
|
||||||
throw new ConvertException("CollectionDecoder not support the type (" + type + ")");
|
throw new ConvertException("CollectionDecoder not support the type (" + type + ")");
|
||||||
}
|
}
|
||||||
@@ -62,9 +62,19 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<T> convertFrom(Reader in) {
|
public Collection<T> convertFrom(Reader in) {
|
||||||
final int len = in.readArrayB();
|
return convertFrom(in, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<T> convertFrom(Reader in, DeMember member) {
|
||||||
|
byte[] typevals = new byte[1];
|
||||||
|
int len = in.readArrayB(member, typevals, componentDecoder);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
if (this.decoder == null) {
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(member, componentDecoder);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
|
if (this.componentDecoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
@@ -75,11 +85,16 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Decodeable<Reader, T> localdecoder = this.decoder;
|
final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
|
||||||
final Collection<T> result = this.creator.create();
|
final Collection<T> result = this.creator.create();
|
||||||
|
boolean first = true;
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
result.add(localdecoder.convertFrom(in));
|
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||||
|
Reader itemReader = getItemReader(in, member, first);
|
||||||
|
if (itemReader == null) break;
|
||||||
|
result.add(readMemberValue(itemReader, member, localdecoder, first));
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
@@ -90,9 +105,33 @@ public final class CollectionDecoder<T> implements Decodeable<Reader, Collection
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||||
|
return in.hasNext(startPosition, contentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
|
||||||
|
return decoder.convertFrom(in);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type getComponentType() {
|
||||||
|
return componentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Decodeable<Reader, T> getComponentDecoder() {
|
||||||
|
return componentDecoder;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,15 +19,15 @@ import java.util.Collection;
|
|||||||
* @param <T> 序列化的集合元素类型
|
* @param <T> 序列化的集合元素类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class CollectionEncoder<T> implements Encodeable<Writer, Collection<T>> {
|
public class CollectionEncoder<T> implements Encodeable<Writer, Collection<T>> {
|
||||||
|
|
||||||
private final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
private final Encodeable<Writer, Object> encoder;
|
protected final Encodeable<Writer, Object> componentEncoder;
|
||||||
|
|
||||||
private boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public CollectionEncoder(final ConvertFactory factory, final Type type) {
|
public CollectionEncoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -35,12 +35,12 @@ public final class CollectionEncoder<T> implements Encodeable<Writer, Collection
|
|||||||
if (type instanceof ParameterizedType) {
|
if (type instanceof ParameterizedType) {
|
||||||
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||||
if (t instanceof TypeVariable) {
|
if (t instanceof TypeVariable) {
|
||||||
this.encoder = factory.getAnyEncoder();
|
this.componentEncoder = factory.getAnyEncoder();
|
||||||
} else {
|
} else {
|
||||||
this.encoder = factory.loadEncoder(t);
|
this.componentEncoder = factory.loadEncoder(t);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.encoder = factory.getAnyEncoder();
|
this.componentEncoder = factory.getAnyEncoder();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
inited = true;
|
inited = true;
|
||||||
@@ -52,16 +52,20 @@ public final class CollectionEncoder<T> implements Encodeable<Writer, Collection
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void convertTo(Writer out, Collection<T> value) {
|
public void convertTo(Writer out, Collection<T> value) {
|
||||||
|
convertTo(out, null, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertTo(Writer out, EnMember member, Collection<T> value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value.isEmpty()) {
|
if (value.isEmpty()) {
|
||||||
out.writeArrayB(0);
|
out.writeArrayB(0, componentEncoder, value);
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.encoder == null) {
|
if (this.componentEncoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
@@ -72,18 +76,31 @@ public final class CollectionEncoder<T> implements Encodeable<Writer, Collection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayB(value.size());
|
if (out.writeArrayB(value.size(), componentEncoder, value) < 0) {
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (Object v : value) {
|
for (Object v : value) {
|
||||||
if (!first) out.writeArrayMark();
|
if (!first) out.writeArrayMark();
|
||||||
encoder.convertTo(out, v);
|
writeValue(out, member, v);
|
||||||
if (first) first = false;
|
if (first) first = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void writeValue(Writer out, EnMember member, Object value) {
|
||||||
|
componentEncoder.convertTo(out, value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Encodeable<Writer, Object> getComponentEncoder() {
|
||||||
|
return componentEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getComponentType() {
|
||||||
|
return componentEncoder == null ? null : componentEncoder.getType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
|
|
||||||
private final ConcurrentHashMap<String, Class> entitys = new ConcurrentHashMap();
|
private final ConcurrentHashMap<String, Class> entitys = new ConcurrentHashMap();
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<Type, Map<String, SimpledCoder<R, W, ?>>> fieldCoders = new ConcurrentHashMap();
|
||||||
|
|
||||||
private final ConcurrentHashMap<Type, Decodeable<R, ?>> decoders = new ConcurrentHashMap();
|
private final ConcurrentHashMap<Type, Decodeable<R, ?>> decoders = new ConcurrentHashMap();
|
||||||
|
|
||||||
private final ConcurrentHashMap<Type, Encodeable<W, ?>> encoders = new ConcurrentHashMap();
|
private final ConcurrentHashMap<Type, Encodeable<W, ?>> encoders = new ConcurrentHashMap();
|
||||||
@@ -53,6 +55,9 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
|
|
||||||
private final Set<Class> skipIgnores = new HashSet();
|
private final Set<Class> skipIgnores = new HashSet();
|
||||||
|
|
||||||
|
//key:需要屏蔽的字段;value:排除的字段名
|
||||||
|
private final ConcurrentHashMap<Class, Set<String>> ignoreAlls = new ConcurrentHashMap();
|
||||||
|
|
||||||
private boolean skipAllIgnore = false;
|
private boolean skipAllIgnore = false;
|
||||||
|
|
||||||
protected ConvertFactory(ConvertFactory<R, W> parent, boolean tiny) {
|
protected ConvertFactory(ConvertFactory<R, W> parent, boolean tiny) {
|
||||||
@@ -136,10 +141,56 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
|
|
||||||
public abstract boolean isReversible(); //是否可逆的
|
public abstract boolean isReversible(); //是否可逆的
|
||||||
|
|
||||||
|
public abstract boolean isFieldSort(); //当ConvertColumn.index相同时是否按字段名称排序
|
||||||
|
|
||||||
public abstract ConvertFactory createChild();
|
public abstract ConvertFactory createChild();
|
||||||
|
|
||||||
public abstract ConvertFactory createChild(boolean tiny);
|
public abstract ConvertFactory createChild(boolean tiny);
|
||||||
|
|
||||||
|
protected SimpledCoder createEnumSimpledCoder(Class enumClass) {
|
||||||
|
return new EnumSimpledCoder(enumClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ObjectDecoder createObjectDecoder(Type type) {
|
||||||
|
return new ObjectDecoder(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ObjectEncoder createObjectEncoder(Type type) {
|
||||||
|
return new ObjectEncoder(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <E> Decodeable<R, E> createMapDecoder(Type type) {
|
||||||
|
return new MapDecoder(this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <E> Encodeable<W, E> createMapEncoder(Type type) {
|
||||||
|
return new MapEncoder(this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <E> Decodeable<R, E> createArrayDecoder(Type type) {
|
||||||
|
return new ArrayDecoder(this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <E> Encodeable<W, E> createArrayEncoder(Type type) {
|
||||||
|
return new ArrayEncoder(this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <E> Decodeable<R, E> createCollectionDecoder(Type type) {
|
||||||
|
return new CollectionDecoder(this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <E> Encodeable<W, E> createCollectionEncoder(Type type) {
|
||||||
|
return new CollectionEncoder(this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <E> Decodeable<R, E> createStreamDecoder(Type type) {
|
||||||
|
return new StreamDecoder(this, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <E> Encodeable<W, E> createStreamEncoder(Type type) {
|
||||||
|
return new StreamEncoder(this, type);
|
||||||
|
}
|
||||||
|
|
||||||
public Convert getConvert() {
|
public Convert getConvert() {
|
||||||
return convert;
|
return convert;
|
||||||
}
|
}
|
||||||
@@ -171,12 +222,19 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
public ConvertColumnEntry findRef(AccessibleObject element) {
|
public ConvertColumnEntry findRef(AccessibleObject element) {
|
||||||
if (element == null) return null;
|
if (element == null) return null;
|
||||||
ConvertColumnEntry en = this.columnEntrys.get(element);
|
ConvertColumnEntry en = this.columnEntrys.get(element);
|
||||||
if (en != null) return en;
|
Set<String> onlyColumns = null;
|
||||||
|
if (element instanceof Method) {
|
||||||
|
onlyColumns = ignoreAlls.get(((Method) element).getDeclaringClass());
|
||||||
|
} else if (element instanceof Field) {
|
||||||
|
onlyColumns = ignoreAlls.get(((Field) element).getDeclaringClass());
|
||||||
|
}
|
||||||
|
if (en != null && onlyColumns == null) return en;
|
||||||
final ConvertType ct = this.getConvertType();
|
final ConvertType ct = this.getConvertType();
|
||||||
ConvertColumn[] ccs = element.getAnnotationsByType(ConvertColumn.class);
|
ConvertColumn[] ccs = element.getAnnotationsByType(ConvertColumn.class);
|
||||||
|
String fieldName = null;
|
||||||
if (ccs.length == 0 && element instanceof Method) {
|
if (ccs.length == 0 && element instanceof Method) {
|
||||||
final Method method = (Method) element;
|
final Method method = (Method) element;
|
||||||
String fieldName = readGetSetFieldName(method);
|
fieldName = readGetSetFieldName(method);
|
||||||
if (fieldName != null) {
|
if (fieldName != null) {
|
||||||
try {
|
try {
|
||||||
ccs = method.getDeclaringClass().getDeclaredField(fieldName).getAnnotationsByType(ConvertColumn.class);
|
ccs = method.getDeclaringClass().getDeclaredField(fieldName).getAnnotationsByType(ConvertColumn.class);
|
||||||
@@ -184,8 +242,22 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (onlyColumns != null && fieldName == null) {
|
||||||
|
if (element instanceof Method) {
|
||||||
|
fieldName = readGetSetFieldName((Method) element);
|
||||||
|
} else if (element instanceof Field) {
|
||||||
|
fieldName = ((Field) element).getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ccs.length == 0 && onlyColumns != null && fieldName != null) {
|
||||||
|
if (!onlyColumns.contains(fieldName)) return new ConvertColumnEntry(fieldName, true);
|
||||||
|
}
|
||||||
for (ConvertColumn ref : ccs) {
|
for (ConvertColumn ref : ccs) {
|
||||||
if (ref.type().contains(ct)) {
|
if (ref.type().contains(ct)) {
|
||||||
|
if (onlyColumns != null && fieldName != null) {
|
||||||
|
String realName = ref.name().isEmpty() ? fieldName : ref.name();
|
||||||
|
if (!onlyColumns.contains(realName)) return new ConvertColumnEntry(realName, true);
|
||||||
|
}
|
||||||
ConvertColumnEntry entry = new ConvertColumnEntry(ref);
|
ConvertColumnEntry entry = new ConvertColumnEntry(ref);
|
||||||
if (skipAllIgnore) {
|
if (skipAllIgnore) {
|
||||||
entry.setIgnore(false);
|
entry.setIgnore(false);
|
||||||
@@ -318,6 +390,22 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
skipIgnores.add(type);
|
skipIgnores.add(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 屏蔽指定类所有字段,仅仅保留指定字段 <br>
|
||||||
|
* <b>注意: 该配置优先级高于skipAllIgnore和ConvertColumnEntry配置</b>
|
||||||
|
*
|
||||||
|
* @param type 指定的类
|
||||||
|
* @param excludeColumns 需要排除的字段名
|
||||||
|
*/
|
||||||
|
public final void registerIgnoreAll(final Class type, String... excludeColumns) {
|
||||||
|
Set<String> set = ignoreAlls.get(type);
|
||||||
|
if (set == null) {
|
||||||
|
ignoreAlls.put(type, new HashSet<>(Arrays.asList(excludeColumns)));
|
||||||
|
} else {
|
||||||
|
set.addAll(Arrays.asList(excludeColumns));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final void register(final Class type, boolean ignore, String... columns) {
|
public final void register(final Class type, boolean ignore, String... columns) {
|
||||||
for (String column : columns) {
|
for (String column : columns) {
|
||||||
register(type, column, new ConvertColumnEntry(column, ignore));
|
register(type, column, new ConvertColumnEntry(column, ignore));
|
||||||
@@ -409,6 +497,29 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
encoders.put(clazz, encoder);
|
encoders.put(clazz, encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//coder = null表示删除该字段的指定SimpledCoder
|
||||||
|
public final <E> void register(final Class clazz, final String field, final SimpledCoder<R, W, E> coder) {
|
||||||
|
if (field == null || clazz == null) return;
|
||||||
|
try {
|
||||||
|
clazz.getDeclaredField(field);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(clazz + " not found field(" + field + ")");
|
||||||
|
}
|
||||||
|
if (coder == null) {
|
||||||
|
Map map = this.fieldCoders.get(clazz);
|
||||||
|
if (map != null) map.remove(field);
|
||||||
|
} else {
|
||||||
|
this.fieldCoders.computeIfAbsent(clazz, c -> new ConcurrentHashMap<>()).put(field, coder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final <E> SimpledCoder<R, W, E> findFieldCoder(final Type clazz, final String field) {
|
||||||
|
if (field == null) return null;
|
||||||
|
Map<String, SimpledCoder<R, W, ?>> map = this.fieldCoders.get(clazz);
|
||||||
|
if (map == null) return parent == null ? null : parent.findFieldCoder(clazz, field);
|
||||||
|
return (SimpledCoder) map.get(field);
|
||||||
|
}
|
||||||
|
|
||||||
public final <E> Decodeable<R, E> findDecoder(final Type type) {
|
public final <E> Decodeable<R, E> findDecoder(final Type type) {
|
||||||
Decodeable<R, E> rs = (Decodeable<R, E>) decoders.get(type);
|
Decodeable<R, E> rs = (Decodeable<R, E>) decoders.get(type);
|
||||||
if (rs != null) return rs;
|
if (rs != null) return rs;
|
||||||
@@ -424,7 +535,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
public final <E> Decodeable<R, E> loadDecoder(final Type type) {
|
public final <E> Decodeable<R, E> loadDecoder(final Type type) {
|
||||||
Decodeable<R, E> decoder = findDecoder(type);
|
Decodeable<R, E> decoder = findDecoder(type);
|
||||||
if (decoder != null) return decoder;
|
if (decoder != null) return decoder;
|
||||||
if (type instanceof GenericArrayType) return new ArrayDecoder(this, type);
|
if (type instanceof GenericArrayType) return createArrayDecoder(type);
|
||||||
Class clazz;
|
Class clazz;
|
||||||
if (type instanceof ParameterizedType) {
|
if (type instanceof ParameterizedType) {
|
||||||
final ParameterizedType pts = (ParameterizedType) type;
|
final ParameterizedType pts = (ParameterizedType) type;
|
||||||
@@ -456,8 +567,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
} else {
|
} else {
|
||||||
throw new ConvertException("not support the type (" + type + ")");
|
throw new ConvertException("not support the type (" + type + ")");
|
||||||
}
|
}
|
||||||
decoder = findDecoder(clazz);
|
//此处不能再findDecoder,否则type与class不一致, 如: RetResult 和 RetResult<Integer>
|
||||||
if (decoder != null) return decoder;
|
|
||||||
return createDecoder(type, clazz);
|
return createDecoder(type, clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,19 +588,19 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
Decodeable<R, E> decoder = null;
|
Decodeable<R, E> decoder = null;
|
||||||
ObjectDecoder od = null;
|
ObjectDecoder od = null;
|
||||||
if (clazz.isEnum()) {
|
if (clazz.isEnum()) {
|
||||||
decoder = new EnumSimpledCoder(clazz);
|
decoder = createEnumSimpledCoder(clazz);
|
||||||
} else if (clazz.isArray()) {
|
} else if (clazz.isArray()) {
|
||||||
decoder = new ArrayDecoder(this, type);
|
decoder = createArrayDecoder(type);
|
||||||
} else if (Collection.class.isAssignableFrom(clazz)) {
|
} else if (Collection.class.isAssignableFrom(clazz)) {
|
||||||
decoder = new CollectionDecoder(this, type);
|
decoder = createCollectionDecoder(type);
|
||||||
} else if (Stream.class.isAssignableFrom(clazz)) {
|
} else if (Stream.class.isAssignableFrom(clazz)) {
|
||||||
decoder = new StreamDecoder(this, type);
|
decoder = createStreamDecoder(type);
|
||||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||||
decoder = new MapDecoder(this, type);
|
decoder = createMapDecoder(type);
|
||||||
} else if (Optional.class == clazz) {
|
} else if (Optional.class == clazz) {
|
||||||
decoder = new OptionalCoder(this, type);
|
decoder = new OptionalCoder(this, type);
|
||||||
} else if (clazz == Object.class) {
|
} else if (clazz == Object.class) {
|
||||||
od = new ObjectDecoder(type);
|
od = createObjectDecoder(type);
|
||||||
decoder = od;
|
decoder = od;
|
||||||
} else if (!clazz.getName().startsWith("java.")
|
} else if (!clazz.getName().startsWith("java.")
|
||||||
|| java.net.HttpCookie.class == clazz
|
|| java.net.HttpCookie.class == clazz
|
||||||
@@ -510,7 +620,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (simpleCoder == null) {
|
if (simpleCoder == null) {
|
||||||
od = new ObjectDecoder(type);
|
od = createObjectDecoder(type);
|
||||||
decoder = od;
|
decoder = od;
|
||||||
} else {
|
} else {
|
||||||
decoder = simpleCoder;
|
decoder = simpleCoder;
|
||||||
@@ -525,7 +635,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
public final <E> Encodeable<W, E> loadEncoder(final Type type) {
|
public final <E> Encodeable<W, E> loadEncoder(final Type type) {
|
||||||
Encodeable<W, E> encoder = findEncoder(type);
|
Encodeable<W, E> encoder = findEncoder(type);
|
||||||
if (encoder != null) return encoder;
|
if (encoder != null) return encoder;
|
||||||
if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
|
if (type instanceof GenericArrayType) return createArrayEncoder(type);
|
||||||
Class clazz;
|
Class clazz;
|
||||||
if (type instanceof ParameterizedType) {
|
if (type instanceof ParameterizedType) {
|
||||||
final ParameterizedType pts = (ParameterizedType) type;
|
final ParameterizedType pts = (ParameterizedType) type;
|
||||||
@@ -543,8 +653,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
} else {
|
} else {
|
||||||
throw new ConvertException("not support the type (" + type + ")");
|
throw new ConvertException("not support the type (" + type + ")");
|
||||||
}
|
}
|
||||||
encoder = findEncoder(clazz);
|
//此处不能再findEncoder,否则type与class不一致, 如: RetResult 和 RetResult<Integer>
|
||||||
if (encoder != null) return encoder;
|
|
||||||
return createEncoder(type, clazz);
|
return createEncoder(type, clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,15 +674,15 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
Encodeable<W, E> encoder = null;
|
Encodeable<W, E> encoder = null;
|
||||||
ObjectEncoder oe = null;
|
ObjectEncoder oe = null;
|
||||||
if (clazz.isEnum()) {
|
if (clazz.isEnum()) {
|
||||||
encoder = new EnumSimpledCoder(clazz);
|
encoder = createEnumSimpledCoder(clazz);
|
||||||
} else if (clazz.isArray()) {
|
} else if (clazz.isArray()) {
|
||||||
encoder = new ArrayEncoder(this, type);
|
encoder = createArrayEncoder(type);
|
||||||
} else if (Collection.class.isAssignableFrom(clazz)) {
|
} else if (Collection.class.isAssignableFrom(clazz)) {
|
||||||
encoder = new CollectionEncoder(this, type);
|
encoder = createCollectionEncoder(type);
|
||||||
} else if (Stream.class.isAssignableFrom(clazz)) {
|
} else if (Stream.class.isAssignableFrom(clazz)) {
|
||||||
encoder = new StreamEncoder(this, type);
|
encoder = createStreamEncoder(type);
|
||||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||||
encoder = new MapEncoder(this, type);
|
encoder = createMapEncoder(type);
|
||||||
} else if (Optional.class == clazz) {
|
} else if (Optional.class == clazz) {
|
||||||
encoder = new OptionalCoder(this, type);
|
encoder = new OptionalCoder(this, type);
|
||||||
} else if (clazz == Object.class) {
|
} else if (clazz == Object.class) {
|
||||||
@@ -594,7 +703,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (simpleCoder == null) {
|
if (simpleCoder == null) {
|
||||||
oe = new ObjectEncoder(type);
|
oe = createObjectEncoder(type);
|
||||||
encoder = oe;
|
encoder = oe;
|
||||||
} else {
|
} else {
|
||||||
encoder = simpleCoder;
|
encoder = simpleCoder;
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ import org.redkale.util.Attribute;
|
|||||||
* @param <F> 字段的数据类型
|
* @param <F> 字段的数据类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class DeMember<R extends Reader, T, F> implements Comparable<DeMember<R, T, F>> {
|
public final class DeMember<R extends Reader, T, F> {
|
||||||
|
|
||||||
protected int index;
|
protected int index;
|
||||||
|
|
||||||
|
protected int position; //从1开始
|
||||||
|
|
||||||
protected final Attribute<T, F> attribute;
|
protected final Attribute<T, F> attribute;
|
||||||
|
|
||||||
protected Decodeable<R, F> decoder;
|
protected Decodeable<R, F> decoder;
|
||||||
@@ -70,15 +72,23 @@ public final class DeMember<R extends Reader, T, F> implements Comparable<DeMemb
|
|||||||
return this.attribute;
|
return this.attribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Decodeable<R, F> getDecoder() {
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return this.index;
|
return this.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public int getPosition() {
|
||||||
public final int compareTo(DeMember<R, T, F> o) {
|
return this.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compareTo(boolean fieldSort, DeMember<R, T, F> o) {
|
||||||
if (o == null) return -1;
|
if (o == null) return -1;
|
||||||
if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index);
|
if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index);
|
||||||
return this.attribute.field().compareTo(o.attribute.field());
|
if (this.index != 0) throw new RuntimeException("fields (" + attribute.field() + ", " + o.attribute.field() + ") have same ConvertColumn.index(" + this.index + ") in " + attribute.declaringClass());
|
||||||
|
return fieldSort ? this.attribute.field().compareTo(o.attribute.field()) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,7 +96,7 @@ public final class DeMember<R extends Reader, T, F> implements Comparable<DeMemb
|
|||||||
if (this == obj) return true;
|
if (this == obj) return true;
|
||||||
if (!(obj instanceof DeMember)) return false;
|
if (!(obj instanceof DeMember)) return false;
|
||||||
DeMember other = (DeMember) obj;
|
DeMember other = (DeMember) obj;
|
||||||
return compareTo(other) == 0;
|
return compareTo(true, other) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.redkale.util.Attribute;
|
|||||||
* @param <F> 字段的数据类型
|
* @param <F> 字段的数据类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class EnMember<W extends Writer, T, F> implements Comparable<EnMember<W, T, F>> {
|
public final class EnMember<W extends Writer, T, F> {
|
||||||
|
|
||||||
final Attribute<T, F> attribute;
|
final Attribute<T, F> attribute;
|
||||||
|
|
||||||
@@ -33,6 +33,8 @@ public final class EnMember<W extends Writer, T, F> implements Comparable<EnMemb
|
|||||||
|
|
||||||
protected int index;
|
protected int index;
|
||||||
|
|
||||||
|
protected int position; //从1开始
|
||||||
|
|
||||||
public EnMember(Attribute<T, F> attribute, Encodeable<W, F> encoder) {
|
public EnMember(Attribute<T, F> attribute, Encodeable<W, F> encoder) {
|
||||||
this.attribute = attribute;
|
this.attribute = attribute;
|
||||||
this.encoder = encoder;
|
this.encoder = encoder;
|
||||||
@@ -63,15 +65,35 @@ public final class EnMember<W extends Writer, T, F> implements Comparable<EnMemb
|
|||||||
return attribute.field().equals(name);
|
return attribute.field().equals(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Attribute<T, F> getAttribute() {
|
||||||
|
return attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Encodeable<W, F> getEncoder() {
|
||||||
|
return encoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStringType() {
|
||||||
|
return istring;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBoolType() {
|
||||||
|
return isbool;
|
||||||
|
}
|
||||||
|
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return this.index;
|
return this.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public int getPosition() {
|
||||||
public final int compareTo(EnMember<W, T, F> o) {
|
return this.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compareTo(boolean fieldSort, EnMember<W, T, F> o) {
|
||||||
if (o == null) return -1;
|
if (o == null) return -1;
|
||||||
if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index);
|
if (this.index != o.index) return (this.index == 0 ? Integer.MAX_VALUE : this.index) - (o.index == 0 ? Integer.MAX_VALUE : o.index);
|
||||||
return this.attribute.field().compareTo(o.attribute.field());
|
if (this.index != 0) throw new RuntimeException("fields (" + attribute.field() + ", " + o.attribute.field() + ") have same ConvertColumn.index(" + this.index + ") in " + attribute.declaringClass());
|
||||||
|
return fieldSort ? this.attribute.field().compareTo(o.attribute.field()) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -79,7 +101,7 @@ public final class EnMember<W extends Writer, T, F> implements Comparable<EnMemb
|
|||||||
if (this == obj) return true;
|
if (this == obj) return true;
|
||||||
if (!(obj instanceof EnMember)) return false;
|
if (!(obj instanceof EnMember)) return false;
|
||||||
EnMember other = (EnMember) obj;
|
EnMember other = (EnMember) obj;
|
||||||
return compareTo(other) == 0;
|
return compareTo(true, other) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -21,13 +21,13 @@ import java.util.Map;
|
|||||||
* @param <V> Map value的数据类型
|
* @param <V> Map value的数据类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
|
public class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
|
||||||
|
|
||||||
private final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
private final Type keyType;
|
protected final Type keyType;
|
||||||
|
|
||||||
private final Type valueType;
|
protected final Type valueType;
|
||||||
|
|
||||||
protected Creator<Map<K, V>> creator;
|
protected Creator<Map<K, V>> creator;
|
||||||
|
|
||||||
@@ -35,14 +35,21 @@ public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
|
|||||||
|
|
||||||
protected final Decodeable<Reader, V> valueDecoder;
|
protected final Decodeable<Reader, V> valueDecoder;
|
||||||
|
|
||||||
private boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public MapDecoder(final ConvertFactory factory, final Type type) {
|
public MapDecoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
try {
|
try {
|
||||||
if (type instanceof ParameterizedType) {
|
if (type == java.util.Properties.class) {
|
||||||
|
this.keyType = String.class;
|
||||||
|
this.valueType = String.class;
|
||||||
|
this.creator = factory.loadCreator(java.util.Properties.class);
|
||||||
|
factory.register(type, this);
|
||||||
|
this.keyDecoder = factory.loadDecoder(String.class);
|
||||||
|
this.valueDecoder = factory.loadDecoder(String.class);
|
||||||
|
} else if (type instanceof ParameterizedType) {
|
||||||
final ParameterizedType pt = (ParameterizedType) type;
|
final ParameterizedType pt = (ParameterizedType) type;
|
||||||
this.keyType = pt.getActualTypeArguments()[0];
|
this.keyType = pt.getActualTypeArguments()[0];
|
||||||
this.valueType = pt.getActualTypeArguments()[1];
|
this.valueType = pt.getActualTypeArguments()[1];
|
||||||
@@ -69,6 +76,10 @@ public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<K, V> convertFrom(Reader in) {
|
public Map<K, V> convertFrom(Reader in) {
|
||||||
|
return convertFrom(in, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<K, V> convertFrom(Reader in, DeMember member) {
|
||||||
if (this.keyDecoder == null || this.valueDecoder == null) {
|
if (this.keyDecoder == null || this.valueDecoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
@@ -80,31 +91,85 @@ public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final int len = in.readMapB();
|
byte[] typevals = new byte[2];
|
||||||
|
int len = in.readMapB(member, typevals, this.keyDecoder, this.valueDecoder);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(member, null);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
final Map<K, V> result = this.creator.create();
|
final Map<K, V> result = this.creator.create();
|
||||||
|
boolean first = true;
|
||||||
|
Decodeable<Reader, K> kdecoder = getKeyDecoder(this.keyDecoder, typevals);
|
||||||
|
Decodeable<Reader, V> vdecoder = getValueDecoder(this.valueDecoder, typevals);
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
K key = keyDecoder.convertFrom(in);
|
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||||
in.readBlank();
|
Reader entryReader = getEntryReader(in, member, first);
|
||||||
V value = valueDecoder.convertFrom(in);
|
if (entryReader == null) break;
|
||||||
|
K key = readKeyMember(entryReader, member, kdecoder, first);
|
||||||
|
entryReader.readBlank();
|
||||||
|
V value = readValueMember(entryReader, member, vdecoder, first);
|
||||||
result.put(key, value);
|
result.put(key, value);
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
K key = keyDecoder.convertFrom(in);
|
K key = readKeyMember(in, member, kdecoder, first);
|
||||||
in.readBlank();
|
in.readBlank();
|
||||||
V value = valueDecoder.convertFrom(in);
|
V value = readValueMember(in, member, vdecoder, first);
|
||||||
result.put(key, value);
|
result.put(key, value);
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in.readMapE();
|
in.readMapE();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||||
|
return in.hasNext(startPosition, contentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Decodeable<Reader, K> getKeyDecoder(Decodeable<Reader, K> decoder, byte[] typevals) {
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Decodeable<Reader, V> getValueDecoder(Decodeable<Reader, V> decoder, byte[] typevals) {
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Reader getEntryReader(Reader in, DeMember member, boolean first) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected K readKeyMember(Reader in, DeMember member, Decodeable<Reader, K> decoder, boolean first) {
|
||||||
|
return decoder.convertFrom(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected V readValueMember(Reader in, DeMember member, Decodeable<Reader, V> decoder, boolean first) {
|
||||||
|
return decoder.convertFrom(in);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type getKeyType() {
|
||||||
|
return keyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getValueType() {
|
||||||
|
return valueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Decodeable<Reader, K> getKeyDecoder() {
|
||||||
|
return keyDecoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Decodeable<Reader, V> getValueDecoder() {
|
||||||
|
return valueDecoder;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,28 +20,28 @@ import java.util.Map;
|
|||||||
* @param <V> Map value的数据类型
|
* @param <V> Map value的数据类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
|
public class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
|
||||||
|
|
||||||
private final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
private final Encodeable<Writer, K> keyencoder;
|
protected final Encodeable<Writer, K> keyEncoder;
|
||||||
|
|
||||||
private final Encodeable<Writer, V> valencoder;
|
protected final Encodeable<Writer, V> valueEncoder;
|
||||||
|
|
||||||
private boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public MapEncoder(final ConvertFactory factory, final Type type) {
|
public MapEncoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
try {
|
try {
|
||||||
if (type instanceof ParameterizedType) {
|
if (type instanceof ParameterizedType) {
|
||||||
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
|
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
|
||||||
this.keyencoder = factory.loadEncoder(pt[0]);
|
this.keyEncoder = factory.loadEncoder(pt[0]);
|
||||||
this.valencoder = factory.loadEncoder(pt[1]);
|
this.valueEncoder = factory.loadEncoder(pt[1]);
|
||||||
} else {
|
} else {
|
||||||
this.keyencoder = factory.getAnyEncoder();
|
this.keyEncoder = factory.getAnyEncoder();
|
||||||
this.valencoder = factory.getAnyEncoder();
|
this.valueEncoder = factory.getAnyEncoder();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
inited = true;
|
inited = true;
|
||||||
@@ -53,13 +53,17 @@ public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void convertTo(Writer out, Map<K, V> value) {
|
public void convertTo(Writer out, Map<K, V> value) {
|
||||||
|
convertTo(out, null, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertTo(Writer out, EnMember member, Map<K, V> value) {
|
||||||
final Map<K, V> values = value;
|
final Map<K, V> values = value;
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.keyencoder == null || this.valencoder == null) {
|
if (this.keyEncoder == null || this.valueEncoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
@@ -70,20 +74,42 @@ public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.writeMapB(values.size());
|
if (out.writeMapB(values.size(), (Encodeable) keyEncoder, (Encodeable) valueEncoder, value) < 0) {
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (Map.Entry<K, V> en : values.entrySet()) {
|
for (Map.Entry<K, V> en : values.entrySet()) {
|
||||||
if (!first) out.writeArrayMark();
|
if (!first) out.writeArrayMark();
|
||||||
this.keyencoder.convertTo(out, en.getKey());
|
writeMemberValue(out, member, en.getKey(), en.getValue(), first);
|
||||||
out.writeMapMark();
|
if (first) first = false;
|
||||||
this.valencoder.convertTo(out, en.getValue());
|
}
|
||||||
if (first) first = false;
|
|
||||||
}
|
}
|
||||||
out.writeMapE();
|
out.writeMapE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void writeMemberValue(Writer out, EnMember member, K key, V value, boolean first) {
|
||||||
|
keyEncoder.convertTo(out, key);
|
||||||
|
out.writeMapMark();
|
||||||
|
valueEncoder.convertTo(out, value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type getKeyType() {
|
||||||
|
return keyEncoder == null ? null : keyEncoder.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getValueType() {
|
||||||
|
return valueEncoder == null ? null : valueEncoder.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Encodeable<Writer, K> getKeyEncoder() {
|
||||||
|
return keyEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Encodeable<Writer, V> getValueEncoder() {
|
||||||
|
return valueEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ package org.redkale.convert;
|
|||||||
|
|
||||||
import org.redkale.util.Creator;
|
import org.redkale.util.Creator;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,7 +21,7 @@ import org.redkale.util.*;
|
|||||||
* @param <T> 反解析的数据类型
|
* @param <T> 反解析的数据类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T> {
|
public class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T> {
|
||||||
|
|
||||||
protected final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
@@ -33,13 +31,13 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
|
|
||||||
protected DeMember<R, T, ?>[] creatorConstructorMembers = new DeMember[0];
|
protected DeMember<R, T, ?>[] creatorConstructorMembers = new DeMember[0];
|
||||||
|
|
||||||
protected DeMember<R, T, ?>[] members;
|
protected DeMember[] members;
|
||||||
|
|
||||||
protected ConvertFactory factory;
|
protected ConvertFactory factory;
|
||||||
|
|
||||||
private boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
protected ObjectDecoder(Type type) {
|
protected ObjectDecoder(Type type) {
|
||||||
this.type = ((type instanceof Class) && ((Class) type).isInterface()) ? Object.class : type;
|
this.type = ((type instanceof Class) && ((Class) type).isInterface()) ? Object.class : type;
|
||||||
@@ -63,7 +61,10 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
public void init(final ConvertFactory factory) {
|
public void init(final ConvertFactory factory) {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
try {
|
try {
|
||||||
if (type == Object.class) return;
|
if (type == Object.class) {
|
||||||
|
this.creatorConstructorMembers = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Class clazz = null;
|
Class clazz = null;
|
||||||
if (type instanceof ParameterizedType) {
|
if (type instanceof ParameterizedType) {
|
||||||
@@ -86,7 +87,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
this.creator = factory.loadCreator(clazz);
|
this.creator = factory.loadCreator(clazz);
|
||||||
if (this.creator == null) throw new ConvertException("Cannot create a creator for " + clazz);
|
if (this.creator == null) throw new ConvertException("Cannot create a creator for " + clazz);
|
||||||
}
|
}
|
||||||
final Set<DeMember> list = new HashSet();
|
final Set<DeMember> list = new LinkedHashSet();
|
||||||
final String[] cps = ObjectEncoder.findConstructorProperties(this.creator);
|
final String[] cps = ObjectEncoder.findConstructorProperties(this.creator);
|
||||||
try {
|
try {
|
||||||
ConvertColumnEntry ref;
|
ConvertColumnEntry ref;
|
||||||
@@ -95,8 +96,12 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
if (factory.isConvertDisabled(field)) continue;
|
if (factory.isConvertDisabled(field)) continue;
|
||||||
ref = factory.findRef(field);
|
ref = factory.findRef(field);
|
||||||
if (ref != null && ref.ignore()) continue;
|
if (ref != null && ref.ignore()) continue;
|
||||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type);
|
Decodeable<R, ?> fieldCoder = factory.findFieldCoder(clazz, field.getName());
|
||||||
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), factory.loadDecoder(t));
|
if (fieldCoder == null) {
|
||||||
|
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type);
|
||||||
|
fieldCoder = factory.loadDecoder(t);
|
||||||
|
}
|
||||||
|
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), fieldCoder);
|
||||||
if (ref != null) member.index = ref.getIndex();
|
if (ref != null) member.index = ref.getIndex();
|
||||||
list.add(member);
|
list.add(member);
|
||||||
}
|
}
|
||||||
@@ -120,8 +125,13 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
}
|
}
|
||||||
ref = factory.findRef(method);
|
ref = factory.findRef(method);
|
||||||
if (ref != null && ref.ignore()) continue;
|
if (ref != null && ref.ignore()) continue;
|
||||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericParameterTypes()[0], this.type), this.type);
|
|
||||||
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), factory.loadDecoder(t));
|
Decodeable<R, ?> fieldCoder = factory.findFieldCoder(clazz, ConvertFactory.readGetSetFieldName(method));
|
||||||
|
if (fieldCoder == null) {
|
||||||
|
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericParameterTypes()[0], this.type), this.type);
|
||||||
|
fieldCoder = factory.loadDecoder(t);
|
||||||
|
}
|
||||||
|
DeMember member = new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), fieldCoder);
|
||||||
if (ref != null) member.index = ref.getIndex();
|
if (ref != null) member.index = ref.getIndex();
|
||||||
list.add(member);
|
list.add(member);
|
||||||
}
|
}
|
||||||
@@ -156,7 +166,20 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.members = list.toArray(new DeMember[list.size()]);
|
this.members = list.toArray(new DeMember[list.size()]);
|
||||||
Arrays.sort(this.members);
|
Arrays.sort(this.members, (a, b) -> a.compareTo(factory.isFieldSort(), b));
|
||||||
|
Set<Integer> pos = new HashSet<>();
|
||||||
|
for (int i = 0; i < this.members.length; i++) {
|
||||||
|
if (this.members[i].index > 0) pos.add(this.members[i].index);
|
||||||
|
}
|
||||||
|
int pidx = 0;
|
||||||
|
for (DeMember member : this.members) {
|
||||||
|
if (member.index > 0) {
|
||||||
|
member.position = member.index;
|
||||||
|
} else {
|
||||||
|
while (pos.contains(++pidx));
|
||||||
|
member.position = pidx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cps != null) {
|
if (cps != null) {
|
||||||
final String[] fields = cps;
|
final String[] fields = cps;
|
||||||
@@ -190,7 +213,7 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
* @return 反解析后的对象结果
|
* @return 反解析后的对象结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final T convertFrom(final R in) {
|
public T convertFrom(final R in) {
|
||||||
final String clazz = in.readObjectB(typeClass);
|
final String clazz = in.readObjectB(typeClass);
|
||||||
if (clazz == null) return null;
|
if (clazz == null) return null;
|
||||||
if (!clazz.isEmpty()) return (T) factory.loadDecoder(factory.getEntityAlias(clazz)).convertFrom(in);
|
if (!clazz.isEmpty()) return (T) factory.loadDecoder(factory.getEntityAlias(clazz)).convertFrom(in);
|
||||||
@@ -209,15 +232,17 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.creatorConstructorMembers == null) { //空构造函数
|
if (this.creatorConstructorMembers == null) { //空构造函数
|
||||||
final T result = this.creator.create();
|
final T result = this.creator == null ? null : this.creator.create();
|
||||||
while (in.hasNext()) {
|
boolean first = true;
|
||||||
|
while (hasNext(in, first)) {
|
||||||
DeMember member = in.readFieldName(members);
|
DeMember member = in.readFieldName(members);
|
||||||
in.readBlank();
|
in.readBlank();
|
||||||
if (member == null) {
|
if (member == null) {
|
||||||
in.skipValue(); //跳过不存在的属性的值
|
in.skipValue(); //跳过不存在的属性的值
|
||||||
} else {
|
} else {
|
||||||
member.read(in, result);
|
readMemberValue(in, member, result, first);
|
||||||
}
|
}
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
in.readObjectE(typeClass);
|
in.readObjectE(typeClass);
|
||||||
return result;
|
return result;
|
||||||
@@ -226,13 +251,14 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
final Object[] constructorParams = new Object[fields.length];
|
final Object[] constructorParams = new Object[fields.length];
|
||||||
final Object[][] otherParams = new Object[this.members.length][2];
|
final Object[][] otherParams = new Object[this.members.length][2];
|
||||||
int oc = 0;
|
int oc = 0;
|
||||||
while (in.hasNext()) {
|
boolean first = true;
|
||||||
|
while (hasNext(in, first)) {
|
||||||
DeMember member = in.readFieldName(members);
|
DeMember member = in.readFieldName(members);
|
||||||
in.readBlank();
|
in.readBlank();
|
||||||
if (member == null) {
|
if (member == null) {
|
||||||
in.skipValue(); //跳过不存在的属性的值
|
in.skipValue(); //跳过不存在的属性的值
|
||||||
} else {
|
} else {
|
||||||
Object val = member.read(in);
|
Object val = readMemberValue(in, member, first);
|
||||||
boolean flag = true;
|
boolean flag = true;
|
||||||
for (int i = 0; i < fields.length; i++) {
|
for (int i = 0; i < fields.length; i++) {
|
||||||
if (member == fields[i]) {
|
if (member == fields[i]) {
|
||||||
@@ -242,9 +268,12 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flag) otherParams[oc++] = new Object[]{member.attribute, val};
|
if (flag) otherParams[oc++] = new Object[]{member.attribute, val};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
in.readObjectE(typeClass);
|
in.readObjectE(typeClass);
|
||||||
|
if (this.creator == null) return null;
|
||||||
final T result = this.creator.create(constructorParams);
|
final T result = this.creator.create(constructorParams);
|
||||||
for (int i = 0; i < oc; i++) {
|
for (int i = 0; i < oc; i++) {
|
||||||
((Attribute) otherParams[i][0]).set(result, otherParams[i][1]);
|
((Attribute) otherParams[i][0]).set(result, otherParams[i][1]);
|
||||||
@@ -253,11 +282,27 @@ public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasNext(R in, boolean first) {
|
||||||
|
return in.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object readMemberValue(R in, DeMember member, boolean first) {
|
||||||
|
return member.read(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void readMemberValue(R in, DeMember member, T result, boolean first) {
|
||||||
|
member.read(in, result);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Type getType() {
|
public Type getType() {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DeMember[] getMembers() {
|
||||||
|
return Arrays.copyOf(members, members.length);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ObjectDecoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
return "ObjectDecoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.redkale.util.*;
|
|||||||
* @param <T> 序列化的数据类型
|
* @param <T> 序列化的数据类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
|
public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
|
||||||
|
|
||||||
static final Type[] TYPEZERO = new Type[0];
|
static final Type[] TYPEZERO = new Type[0];
|
||||||
|
|
||||||
@@ -32,9 +32,9 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
|||||||
|
|
||||||
protected ConvertFactory factory;
|
protected ConvertFactory factory;
|
||||||
|
|
||||||
private boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
protected ObjectEncoder(Type type) {
|
protected ObjectEncoder(Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -61,7 +61,7 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
|||||||
if (type == Object.class) return;
|
if (type == Object.class) return;
|
||||||
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
|
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
|
||||||
final Class clazz = this.typeClass;
|
final Class clazz = this.typeClass;
|
||||||
final Set<EnMember> list = new HashSet();
|
final Set<EnMember> list = new LinkedHashSet();
|
||||||
final boolean reversible = factory.isReversible();
|
final boolean reversible = factory.isReversible();
|
||||||
Creator creator = null;
|
Creator creator = null;
|
||||||
try {
|
try {
|
||||||
@@ -77,8 +77,12 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
|||||||
if (factory.isConvertDisabled(field)) continue;
|
if (factory.isConvertDisabled(field)) continue;
|
||||||
ref = factory.findRef(field);
|
ref = factory.findRef(field);
|
||||||
if (ref != null && ref.ignore()) continue;
|
if (ref != null && ref.ignore()) continue;
|
||||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type);
|
Encodeable<W, ?> fieldCoder = factory.findFieldCoder(clazz, field.getName());
|
||||||
EnMember member = new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t));
|
if (fieldCoder == null) {
|
||||||
|
Type t = TypeToken.createClassType(TypeToken.getGenericType(field.getGenericType(), this.type), this.type);
|
||||||
|
fieldCoder = factory.loadEncoder(t);
|
||||||
|
}
|
||||||
|
EnMember member = new EnMember(createAttribute(factory, clazz, field, null, null), fieldCoder);
|
||||||
if (ref != null) member.index = ref.getIndex();
|
if (ref != null) member.index = ref.getIndex();
|
||||||
list.add(member);
|
list.add(member);
|
||||||
}
|
}
|
||||||
@@ -102,13 +106,30 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
|||||||
}
|
}
|
||||||
ref = factory.findRef(method);
|
ref = factory.findRef(method);
|
||||||
if (ref != null && ref.ignore()) continue;
|
if (ref != null && ref.ignore()) continue;
|
||||||
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericReturnType(), this.type), this.type);
|
Encodeable<W, ?> fieldCoder = factory.findFieldCoder(clazz, ConvertFactory.readGetSetFieldName(method));
|
||||||
EnMember member = new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t));
|
if (fieldCoder == null) {
|
||||||
|
Type t = TypeToken.createClassType(TypeToken.getGenericType(method.getGenericReturnType(), this.type), this.type);
|
||||||
|
fieldCoder = factory.loadEncoder(t);
|
||||||
|
}
|
||||||
|
EnMember member = new EnMember(createAttribute(factory, clazz, null, method, null), fieldCoder);
|
||||||
if (ref != null) member.index = ref.getIndex();
|
if (ref != null) member.index = ref.getIndex();
|
||||||
list.add(member);
|
list.add(member);
|
||||||
}
|
}
|
||||||
this.members = list.toArray(new EnMember[list.size()]);
|
this.members = list.toArray(new EnMember[list.size()]);
|
||||||
Arrays.sort(this.members);
|
Arrays.sort(this.members, (a, b) -> a.compareTo(factory.isFieldSort(), b));
|
||||||
|
Set<Integer> pos = new HashSet<>();
|
||||||
|
for (int i = 0; i < this.members.length; i++) {
|
||||||
|
if (this.members[i].index > 0) pos.add(this.members[i].index);
|
||||||
|
}
|
||||||
|
int pidx = 0;
|
||||||
|
for (EnMember member : this.members) {
|
||||||
|
if (member.index > 0) {
|
||||||
|
member.position = member.index;
|
||||||
|
} else {
|
||||||
|
while (pos.contains(++pidx));
|
||||||
|
member.position = pidx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new ConvertException(ex);
|
throw new ConvertException(ex);
|
||||||
@@ -122,7 +143,7 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void convertTo(W out, T value) {
|
public void convertTo(W out, T value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeObjectNull(null);
|
out.writeObjectNull(null);
|
||||||
return;
|
return;
|
||||||
@@ -136,24 +157,29 @@ public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value.getClass() != this.typeClass) {
|
if (value.getClass() != this.typeClass && !this.type.equals(out.specify())) {
|
||||||
final Class clz = value.getClass();
|
final Class clz = value.getClass();
|
||||||
if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clz));
|
if (out.needWriteClassName()) out.writeClassName(factory.getEntityAlias(clz));
|
||||||
factory.loadEncoder(clz).convertTo(out, value);
|
factory.loadEncoder(clz).convertTo(out, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.writeObjectB(value);
|
if (out.writeObjectB(value) < 0) {
|
||||||
for (EnMember member : members) {
|
for (EnMember member : members) {
|
||||||
out.writeObjectField(member, value);
|
out.writeObjectField(member, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeObjectE(value);
|
out.writeObjectE(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Type getType() {
|
public Type getType() {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EnMember[] getMembers() {
|
||||||
|
return Arrays.copyOf(members, members.length);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
|
||||||
|
|||||||
@@ -30,10 +30,11 @@ public class OptionalCoder<R extends Reader, W extends Writer, T> extends Simple
|
|||||||
|
|
||||||
protected final Encodeable<Writer, T> encoder;
|
protected final Encodeable<Writer, T> encoder;
|
||||||
|
|
||||||
private boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public OptionalCoder(final ConvertFactory factory, final Type type) {
|
public OptionalCoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -22,12 +22,46 @@ public abstract class Reader {
|
|||||||
|
|
||||||
public static final short SIGN_NOLENGTH = -2;
|
public static final short SIGN_NOLENGTH = -2;
|
||||||
|
|
||||||
|
public static final short SIGN_NOLENBUTBYTES = -3; //目前只适合于protobuf的boolean[]...double[]类型
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否还存在下个元素或字段
|
* 是否还存在下个元素或字段 <br>
|
||||||
|
* 注意: 主要用于Array、Collection、Stream或Map等集合对象
|
||||||
|
*
|
||||||
|
* @param startPosition 起始位置
|
||||||
|
* @param contentLength 内容大小, 不确定的传-1
|
||||||
*
|
*
|
||||||
* @return 是否还存在下个元素或字段
|
* @return 是否还存在下个元素或字段
|
||||||
*/
|
*/
|
||||||
public abstract boolean hasNext();
|
public abstract boolean hasNext(int startPosition, int contentLength);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否还存在下个元素或字段
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return 是否还存在下个元素或字段
|
||||||
|
*/
|
||||||
|
public boolean hasNext() {
|
||||||
|
return hasNext(-1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前位置
|
||||||
|
*
|
||||||
|
* @return 当前位置
|
||||||
|
*/
|
||||||
|
public abstract int position();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取字段值内容的字节数 <br>
|
||||||
|
* 只有在readXXXB方法返回SIGN_NOLENBUTBYTES值才会调用此方法
|
||||||
|
*
|
||||||
|
* @param member DeMember
|
||||||
|
* @param decoder Decodeable
|
||||||
|
*
|
||||||
|
* @return 内容大小, 不确定返回-1
|
||||||
|
*/
|
||||||
|
public abstract int readMemberContentLength(DeMember member, Decodeable decoder);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跳过值(不包含值前面的字段)
|
* 跳过值(不包含值前面的字段)
|
||||||
@@ -61,9 +95,13 @@ public abstract class Reader {
|
|||||||
/**
|
/**
|
||||||
* 读取数组的开头并返回数组的长度
|
* 读取数组的开头并返回数组的长度
|
||||||
*
|
*
|
||||||
|
* @param member DeMember
|
||||||
|
* @param typevals byte[]
|
||||||
|
* @param componentDecoder Decodeable
|
||||||
|
*
|
||||||
* @return 返回数组的长度
|
* @return 返回数组的长度
|
||||||
*/
|
*/
|
||||||
public abstract int readArrayB();
|
public abstract int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取数组的尾端
|
* 读取数组的尾端
|
||||||
@@ -74,9 +112,14 @@ public abstract class Reader {
|
|||||||
/**
|
/**
|
||||||
* 读取map的开头并返回map的size
|
* 读取map的开头并返回map的size
|
||||||
*
|
*
|
||||||
|
* @param member DeMember
|
||||||
|
* @param typevals byte[]
|
||||||
|
* @param keyDecoder Decodeable
|
||||||
|
* @param valueDecoder Decodeable
|
||||||
|
*
|
||||||
* @return 返回map的size
|
* @return 返回map的size
|
||||||
*/
|
*/
|
||||||
public abstract int readMapB();
|
public abstract int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取数组的尾端
|
* 读取数组的尾端
|
||||||
@@ -107,6 +150,13 @@ public abstract class Reader {
|
|||||||
*/
|
*/
|
||||||
public abstract byte readByte();
|
public abstract byte readByte();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取byte[]
|
||||||
|
*
|
||||||
|
* @return byte[]
|
||||||
|
*/
|
||||||
|
public abstract byte[] readByteArray();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取一个char值
|
* 读取一个char值
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import java.lang.reflect.Type;
|
|||||||
*/
|
*/
|
||||||
public abstract class SimpledCoder<R extends Reader, W extends Writer, T> implements Decodeable<R, T>, Encodeable<W, T> {
|
public abstract class SimpledCoder<R extends Reader, W extends Writer, T> implements Decodeable<R, T>, Encodeable<W, T> {
|
||||||
|
|
||||||
private Type type;
|
protected Type type;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract void convertTo(final W out, final T value);
|
public abstract void convertTo(final W out, final T value);
|
||||||
|
|||||||
@@ -22,19 +22,19 @@ import java.util.stream.Stream;
|
|||||||
* @param <T> 反解析的集合元素类型
|
* @param <T> 反解析的集合元素类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> {
|
public class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> {
|
||||||
|
|
||||||
private final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
private final Type componentType;
|
protected final Type componentType;
|
||||||
|
|
||||||
protected Creator<Stream<T>> creator;
|
protected Creator<Stream<T>> creator;
|
||||||
|
|
||||||
protected final Decodeable<Reader, T> decoder;
|
protected final Decodeable<Reader, T> componentDecoder;
|
||||||
|
|
||||||
private boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public StreamDecoder(final ConvertFactory factory, final Type type) {
|
public StreamDecoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -44,7 +44,7 @@ public final class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> {
|
|||||||
this.componentType = pt.getActualTypeArguments()[0];
|
this.componentType = pt.getActualTypeArguments()[0];
|
||||||
this.creator = factory.loadCreator((Class) pt.getRawType());
|
this.creator = factory.loadCreator((Class) pt.getRawType());
|
||||||
factory.register(type, this);
|
factory.register(type, this);
|
||||||
this.decoder = factory.loadDecoder(this.componentType);
|
this.componentDecoder = factory.loadDecoder(this.componentType);
|
||||||
} else {
|
} else {
|
||||||
throw new ConvertException("StreamDecoder not support the type (" + type + ")");
|
throw new ConvertException("StreamDecoder not support the type (" + type + ")");
|
||||||
}
|
}
|
||||||
@@ -58,9 +58,19 @@ public final class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stream<T> convertFrom(Reader in) {
|
public Stream<T> convertFrom(Reader in) {
|
||||||
final int len = in.readArrayB();
|
return convertFrom(in, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<T> convertFrom(Reader in, DeMember member) {
|
||||||
|
byte[] typevals = new byte[1];
|
||||||
|
int len = in.readArrayB(member, typevals, this.componentDecoder);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
if (this.decoder == null) {
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(member, this.componentDecoder);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
|
if (this.componentDecoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
@@ -71,11 +81,16 @@ public final class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Decodeable<Reader, T> localdecoder = this.decoder;
|
final Decodeable<Reader, T> localdecoder = getComponentDecoder(this.componentDecoder, typevals);
|
||||||
final List<T> result = new ArrayList();
|
final List<T> result = new ArrayList();
|
||||||
|
boolean first = true;
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
result.add(localdecoder.convertFrom(in));
|
while (hasNext(in, member, startPosition, contentLength, first)) {
|
||||||
|
Reader itemReader = getItemReader(in, member, first);
|
||||||
|
if (itemReader == null) break;
|
||||||
|
result.add(readMemberValue(itemReader, member, localdecoder, first));
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
@@ -86,9 +101,33 @@ public final class StreamDecoder<T> implements Decodeable<Reader, Stream<T>> {
|
|||||||
return result.stream();
|
return result.stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasNext(Reader in, DeMember member, int startPosition, int contentLength, boolean first) {
|
||||||
|
return in.hasNext(startPosition, contentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Reader getItemReader(Reader in, DeMember member, boolean first) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected T readMemberValue(Reader in, DeMember member, Decodeable<Reader, T> decoder, boolean first) {
|
||||||
|
return decoder.convertFrom(in);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type getComponentType() {
|
||||||
|
return componentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Decodeable<Reader, T> getComponentDecoder() {
|
||||||
|
return componentDecoder;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,15 +19,15 @@ import java.util.stream.Stream;
|
|||||||
* @param <T> 序列化的集合元素类型
|
* @param <T> 序列化的集合元素类型
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> {
|
public class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> {
|
||||||
|
|
||||||
private final Type type;
|
protected final Type type;
|
||||||
|
|
||||||
private final Encodeable<Writer, Object> encoder;
|
protected final Encodeable<Writer, Object> componentEncoder;
|
||||||
|
|
||||||
private boolean inited = false;
|
protected volatile boolean inited = false;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
|
|
||||||
public StreamEncoder(final ConvertFactory factory, final Type type) {
|
public StreamEncoder(final ConvertFactory factory, final Type type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -35,12 +35,12 @@ public final class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> {
|
|||||||
if (type instanceof ParameterizedType) {
|
if (type instanceof ParameterizedType) {
|
||||||
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||||
if (t instanceof TypeVariable) {
|
if (t instanceof TypeVariable) {
|
||||||
this.encoder = factory.getAnyEncoder();
|
this.componentEncoder = factory.getAnyEncoder();
|
||||||
} else {
|
} else {
|
||||||
this.encoder = factory.loadEncoder(t);
|
this.componentEncoder = factory.loadEncoder(t);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.encoder = factory.getAnyEncoder();
|
this.componentEncoder = factory.getAnyEncoder();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
inited = true;
|
inited = true;
|
||||||
@@ -52,17 +52,21 @@ public final class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void convertTo(Writer out, Stream<T> value) {
|
public void convertTo(Writer out, Stream<T> value) {
|
||||||
|
convertTo(out, null, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void convertTo(Writer out, EnMember member, Stream<T> value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Object[] array = value.toArray();
|
Object[] array = value.toArray();
|
||||||
if (array.length == 0) {
|
if (array.length == 0) {
|
||||||
out.writeArrayB(0);
|
out.writeArrayB(0, componentEncoder, array);
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.encoder == null) {
|
if (this.componentEncoder == null) {
|
||||||
if (!this.inited) {
|
if (!this.inited) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
@@ -73,18 +77,31 @@ public final class StreamEncoder<T> implements Encodeable<Writer, Stream<T>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayB(array.length);
|
if (out.writeArrayB(array.length, componentEncoder, array) < 0) {
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (Object v : array) {
|
for (Object v : array) {
|
||||||
if (!first) out.writeArrayMark();
|
if (!first) out.writeArrayMark();
|
||||||
encoder.convertTo(out, v);
|
writeMemberValue(out, member, v, first);
|
||||||
if (first) first = false;
|
if (first) first = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void writeMemberValue(Writer out, EnMember member, Object value, boolean first) {
|
||||||
|
componentEncoder.convertTo(out, value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Encodeable<Writer, Object> getComponentEncoder() {
|
||||||
|
return componentEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getComponentType() {
|
||||||
|
return componentEncoder == null ? null : componentEncoder.getType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.convert;
|
package org.redkale.convert;
|
||||||
|
|
||||||
import org.redkale.util.Attribute;
|
import java.lang.reflect.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化的数据输出流
|
* 序列化的数据输出流
|
||||||
@@ -20,6 +20,33 @@ public abstract class Writer {
|
|||||||
//当前对象输出字段名之前是否需要分隔符, JSON字段间的分隔符为,逗号
|
//当前对象输出字段名之前是否需要分隔符, JSON字段间的分隔符为,逗号
|
||||||
protected boolean comma;
|
protected boolean comma;
|
||||||
|
|
||||||
|
//convertTo时是否以指定Type的ObjectEncoder进行处理
|
||||||
|
protected Type specify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置specify
|
||||||
|
*
|
||||||
|
* @param value Type
|
||||||
|
*/
|
||||||
|
public void specify(Type value) {
|
||||||
|
if (value instanceof GenericArrayType) {
|
||||||
|
this.specify = ((GenericArrayType) value).getGenericComponentType();
|
||||||
|
} else if (value instanceof Class && ((Class) value).isArray()) {
|
||||||
|
this.specify = ((Class) value).getComponentType();
|
||||||
|
} else {
|
||||||
|
this.specify = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回specify
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public Type specify() {
|
||||||
|
return this.specify;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当tiny=true时, 字符串为空、boolean为false的字段值都会被跳过, 不会输出。
|
* 当tiny=true时, 字符串为空、boolean为false的字段值都会被跳过, 不会输出。
|
||||||
*
|
*
|
||||||
@@ -51,9 +78,12 @@ public abstract class Writer {
|
|||||||
* 注: 覆盖此方法必须要先调用父方法 super.writeObjectB(obj);
|
* 注: 覆盖此方法必须要先调用父方法 super.writeObjectB(obj);
|
||||||
*
|
*
|
||||||
* @param obj 写入的对象
|
* @param obj 写入的对象
|
||||||
|
*
|
||||||
|
* @return 返回-1表示还没有写入对象内容,大于-1表示已写入对象内容,返回对象内容大小
|
||||||
*/
|
*/
|
||||||
public void writeObjectB(Object obj) {
|
public int writeObjectB(Object obj) {
|
||||||
this.comma = false;
|
this.comma = false;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,7 +104,7 @@ public abstract class Writer {
|
|||||||
* @param obj 写入的对象
|
* @param obj 写入的对象
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final void writeObjectField(final EnMember member, Object obj) {
|
public void writeObjectField(final EnMember member, Object obj) {
|
||||||
Object value = member.attribute.get(obj);
|
Object value = member.attribute.get(obj);
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
if (tiny()) {
|
if (tiny()) {
|
||||||
@@ -84,7 +114,7 @@ public abstract class Writer {
|
|||||||
if (!((Boolean) value)) return;
|
if (!((Boolean) value)) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.writeFieldName(member.attribute);
|
this.writeFieldName(member);
|
||||||
member.encoder.convertTo(this, value);
|
member.encoder.convertTo(this, value);
|
||||||
this.comma = true;
|
this.comma = true;
|
||||||
}
|
}
|
||||||
@@ -99,9 +129,13 @@ public abstract class Writer {
|
|||||||
/**
|
/**
|
||||||
* 输出一个数组前的操作
|
* 输出一个数组前的操作
|
||||||
*
|
*
|
||||||
* @param size 数组长度
|
* @param size 数组长度
|
||||||
|
* @param componentEncoder Encodeable
|
||||||
|
* @param obj 对象
|
||||||
|
*
|
||||||
|
* @return 返回-1表示还没有写入对象内容,大于-1表示已写入对象内容,返回对象内容大小
|
||||||
*/
|
*/
|
||||||
public abstract void writeArrayB(int size);
|
public abstract int writeArrayB(int size, Encodeable<Writer, Object> componentEncoder, Object obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输出数组元素间的间隔符
|
* 输出数组元素间的间隔符
|
||||||
@@ -118,9 +152,14 @@ public abstract class Writer {
|
|||||||
/**
|
/**
|
||||||
* 输出一个Map前的操作
|
* 输出一个Map前的操作
|
||||||
*
|
*
|
||||||
* @param size map大小
|
* @param size map大小
|
||||||
|
* @param keyEncoder Encodeable
|
||||||
|
* @param valueEncoder Encodeable
|
||||||
|
* @param obj 对象
|
||||||
|
*
|
||||||
|
* @return 返回-1表示还没有写入对象内容,大于-1表示已写入对象内容,返回对象内容大小
|
||||||
*/
|
*/
|
||||||
public abstract void writeMapB(int size);
|
public abstract int writeMapB(int size, Encodeable<Writer, Object> keyEncoder, Encodeable<Writer, Object> valueEncoder, Object obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输出一个Map中key与value间的间隔符
|
* 输出一个Map中key与value间的间隔符
|
||||||
@@ -137,9 +176,9 @@ public abstract class Writer {
|
|||||||
/**
|
/**
|
||||||
* 输出一个字段名
|
* 输出一个字段名
|
||||||
*
|
*
|
||||||
* @param attribute 字段的Attribute对象
|
* @param member 字段的EnMember对象
|
||||||
*/
|
*/
|
||||||
public abstract void writeFieldName(Attribute attribute);
|
public abstract void writeFieldName(EnMember member);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写入一个boolean值
|
* 写入一个boolean值
|
||||||
@@ -155,6 +194,13 @@ public abstract class Writer {
|
|||||||
*/
|
*/
|
||||||
public abstract void writeByte(byte value);
|
public abstract void writeByte(byte value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写入byte[]
|
||||||
|
*
|
||||||
|
* @param values byte[]
|
||||||
|
*/
|
||||||
|
public abstract void writeByteArray(byte[] values);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写入一个char值
|
* 写入一个char值
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package org.redkale.convert.bson;
|
|||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
import static org.redkale.convert.Reader.SIGN_NULL;
|
import static org.redkale.convert.Reader.SIGN_NULL;
|
||||||
|
import org.redkale.convert.ext.ByteSimpledCoder;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,16 +49,38 @@ public class BsonByteBufferReader extends BsonReader {
|
|||||||
return mask == null ? currentBuffer.get(currentBuffer.position()) : mask.unmask(currentBuffer.get(currentBuffer.position()));
|
return mask == null ? currentBuffer.get(currentBuffer.position()) : mask.unmask(currentBuffer.get(currentBuffer.position()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder) {
|
||||||
|
short bt = readShort();
|
||||||
|
if (bt == Reader.SIGN_NULL) return bt;
|
||||||
|
short lt = readShort();
|
||||||
|
byte kt = readByte();
|
||||||
|
byte vt = readByte();
|
||||||
|
if (typevals != null) {
|
||||||
|
typevals[0] = kt;
|
||||||
|
typevals[1] = vt;
|
||||||
|
}
|
||||||
|
return (bt & 0xffff) << 16 | (lt & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断下一个非空白字节是否为[
|
* 判断下一个非空白字节是否为[
|
||||||
*
|
*
|
||||||
|
* @param member DeMember
|
||||||
|
* @param typevals byte[]
|
||||||
|
* @param componentDecoder Decodeable
|
||||||
|
*
|
||||||
* @return 数组长度或 SIGN_NULL
|
* @return 数组长度或 SIGN_NULL
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final int readArrayB() {
|
public final int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) {
|
||||||
short bt = readShort();
|
short bt = readShort();
|
||||||
if (bt == Reader.SIGN_NULL) return bt;
|
if (bt == Reader.SIGN_NULL) return bt;
|
||||||
short lt = readShort();
|
short lt = readShort();
|
||||||
|
if (componentDecoder != null && componentDecoder != ByteSimpledCoder.instance) {
|
||||||
|
byte comval = readByte();
|
||||||
|
if (typevals != null) typevals[0] = comval;
|
||||||
|
}
|
||||||
return (bt & 0xffff) << 16 | (lt & 0xffff);
|
return (bt & 0xffff) << 16 | (lt & 0xffff);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ public class BsonByteBufferWriter extends BsonWriter {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean recycle() {
|
protected boolean recycle() {
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
|
this.specify = null;
|
||||||
this.buffers = null;
|
this.buffers = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,12 @@
|
|||||||
package org.redkale.convert.bson;
|
package org.redkale.convert.bson;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
import org.redkale.util.AnyValue;
|
import org.redkale.convert.ext.*;
|
||||||
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BSON的ConvertFactory
|
* BSON的ConvertFactory
|
||||||
@@ -26,6 +30,16 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
|
|||||||
|
|
||||||
static final Encodeable objectEncoder = instance.loadEncoder(Object.class);
|
static final Encodeable objectEncoder = instance.loadEncoder(Object.class);
|
||||||
|
|
||||||
|
static final Decodeable skipArrayDecoder = new SkipArrayDecoder(instance, Object[].class);
|
||||||
|
|
||||||
|
static final Decodeable skipCollectionDecoder = new SkipCollectionDecoder(instance, new TypeToken<Collection<Object>>() {
|
||||||
|
}.getType());
|
||||||
|
|
||||||
|
static final Decodeable skipStreamDecoder = new SkipStreamDecoder(instance, new TypeToken<Stream<Object>>() {
|
||||||
|
}.getType());
|
||||||
|
|
||||||
|
static final Decodeable skipMapDecoder = new SkipMapDecoder(instance, Map.class);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
instance.register(Serializable.class, objectDecoder);
|
instance.register(Serializable.class, objectDecoder);
|
||||||
instance.register(Serializable.class, objectEncoder);
|
instance.register(Serializable.class, objectEncoder);
|
||||||
@@ -84,4 +98,115 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFieldSort() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static byte typeEnum(final Type type) {
|
||||||
|
return typeEnum(TypeToken.typeToClass(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static byte typeEnum(final Class type) {
|
||||||
|
Objects.requireNonNull(type);
|
||||||
|
byte typeval = 127; //字段的类型值
|
||||||
|
if (type == boolean.class || type == Boolean.class) {
|
||||||
|
typeval = 11;
|
||||||
|
} else if (type == byte.class || type == Byte.class) {
|
||||||
|
typeval = 12;
|
||||||
|
} else if (type == short.class || type == Short.class) {
|
||||||
|
typeval = 13;
|
||||||
|
} else if (type == char.class || type == Character.class) {
|
||||||
|
typeval = 14;
|
||||||
|
} else if (type == int.class || type == Integer.class) {
|
||||||
|
typeval = 15;
|
||||||
|
} else if (type == long.class || type == Long.class) {
|
||||||
|
typeval = 16;
|
||||||
|
} else if (type == float.class || type == Float.class) {
|
||||||
|
typeval = 17;
|
||||||
|
} else if (type == double.class || type == Double.class) {
|
||||||
|
typeval = 18;
|
||||||
|
} else if (type == String.class) {
|
||||||
|
typeval = 19;
|
||||||
|
} else if (type == boolean[].class || type == Boolean[].class) {
|
||||||
|
typeval = 21;
|
||||||
|
} else if (type == byte[].class || type == Byte[].class) {
|
||||||
|
typeval = 22;
|
||||||
|
} else if (type == short[].class || type == Short[].class) {
|
||||||
|
typeval = 23;
|
||||||
|
} else if (type == char[].class || type == Character[].class) {
|
||||||
|
typeval = 24;
|
||||||
|
} else if (type == int[].class || type == Integer[].class) {
|
||||||
|
typeval = 25;
|
||||||
|
} else if (type == long[].class || type == Long[].class) {
|
||||||
|
typeval = 26;
|
||||||
|
} else if (type == float[].class || type == Float[].class) {
|
||||||
|
typeval = 27;
|
||||||
|
} else if (type == double[].class || type == Double[].class) {
|
||||||
|
typeval = 28;
|
||||||
|
} else if (type == String[].class) {
|
||||||
|
typeval = 29;
|
||||||
|
} else if (type.isArray()) {
|
||||||
|
typeval = 81;
|
||||||
|
} else if (Collection.class.isAssignableFrom(type)) {
|
||||||
|
typeval = 82;
|
||||||
|
} else if (Stream.class.isAssignableFrom(type)) {
|
||||||
|
typeval = 83;
|
||||||
|
} else if (Map.class.isAssignableFrom(type)) {
|
||||||
|
typeval = 84;
|
||||||
|
}
|
||||||
|
return typeval;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Decodeable typeEnum(final byte typeval) {
|
||||||
|
switch (typeval) {
|
||||||
|
case 11:
|
||||||
|
return BoolSimpledCoder.instance;
|
||||||
|
case 12:
|
||||||
|
return ByteSimpledCoder.instance;
|
||||||
|
case 13:
|
||||||
|
return ShortSimpledCoder.instance;
|
||||||
|
case 14:
|
||||||
|
return CharSimpledCoder.instance;
|
||||||
|
case 15:
|
||||||
|
return IntSimpledCoder.instance;
|
||||||
|
case 16:
|
||||||
|
return LongSimpledCoder.instance;
|
||||||
|
case 17:
|
||||||
|
return FloatSimpledCoder.instance;
|
||||||
|
case 18:
|
||||||
|
return DoubleSimpledCoder.instance;
|
||||||
|
case 19:
|
||||||
|
return StringSimpledCoder.instance;
|
||||||
|
case 21:
|
||||||
|
return BoolArraySimpledCoder.instance;
|
||||||
|
case 22:
|
||||||
|
return ByteArraySimpledCoder.instance;
|
||||||
|
case 23:
|
||||||
|
return ShortArraySimpledCoder.instance;
|
||||||
|
case 24:
|
||||||
|
return CharArraySimpledCoder.instance;
|
||||||
|
case 25:
|
||||||
|
return IntArraySimpledCoder.instance;
|
||||||
|
case 26:
|
||||||
|
return LongArraySimpledCoder.instance;
|
||||||
|
case 27:
|
||||||
|
return FloatArraySimpledCoder.instance;
|
||||||
|
case 28:
|
||||||
|
return DoubleArraySimpledCoder.instance;
|
||||||
|
case 29:
|
||||||
|
return StringArraySimpledCoder.instance;
|
||||||
|
case 81:
|
||||||
|
return skipArrayDecoder;
|
||||||
|
case 82:
|
||||||
|
return skipCollectionDecoder;
|
||||||
|
case 83:
|
||||||
|
return skipStreamDecoder;
|
||||||
|
case 84:
|
||||||
|
return skipMapDecoder;
|
||||||
|
case 127:
|
||||||
|
return BsonFactory.objectDecoder;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,53 +93,27 @@ public class BsonReader extends Reader {
|
|||||||
final byte val = this.typeval;
|
final byte val = this.typeval;
|
||||||
this.typeval = 0;
|
this.typeval = 0;
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 1: readBoolean();
|
case 11: readBoolean();
|
||||||
break;
|
break;
|
||||||
case 2: readByte();
|
case 12: readByte();
|
||||||
break;
|
break;
|
||||||
case 3: readShort();
|
case 13: readShort();
|
||||||
break;
|
break;
|
||||||
case 4: readChar();
|
case 14: readChar();
|
||||||
break;
|
break;
|
||||||
case 5: readInt();
|
case 15: readInt();
|
||||||
break;
|
break;
|
||||||
case 6: readLong();
|
case 16: readLong();
|
||||||
break;
|
break;
|
||||||
case 7: readFloat();
|
case 17: readFloat();
|
||||||
break;
|
break;
|
||||||
case 8: readDouble();
|
case 18: readDouble();
|
||||||
break;
|
break;
|
||||||
case 9: readString();
|
case 19: readString();
|
||||||
break;
|
break;
|
||||||
case 101:
|
default:
|
||||||
BoolArraySimpledCoder.instance.convertFrom(this);
|
Decodeable decoder = BsonFactory.typeEnum(val);
|
||||||
break;
|
if (decoder != null) decoder.convertFrom(this);
|
||||||
case 102:
|
|
||||||
ByteArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 103:
|
|
||||||
ShortArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 104:
|
|
||||||
CharArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 105:
|
|
||||||
IntArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 106:
|
|
||||||
LongArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 107:
|
|
||||||
FloatArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 108:
|
|
||||||
DoubleArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 109:
|
|
||||||
StringArraySimpledCoder.instance.convertFrom(this);
|
|
||||||
break;
|
|
||||||
case 127:
|
|
||||||
BsonFactory.objectDecoder.convertFrom(this);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,8 +145,17 @@ public class BsonReader extends Reader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int readMapB() {
|
public int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valueDecoder) {
|
||||||
return readArrayB();
|
short bt = readShort();
|
||||||
|
if (bt == Reader.SIGN_NULL) return bt;
|
||||||
|
int rs = (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
|
||||||
|
byte kt = readByte();
|
||||||
|
byte vt = readByte();
|
||||||
|
if (typevals != null) {
|
||||||
|
typevals[0] = kt;
|
||||||
|
typevals[1] = vt;
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -185,10 +168,15 @@ public class BsonReader extends Reader {
|
|||||||
* @return 数组长度或SIGN_NULL
|
* @return 数组长度或SIGN_NULL
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int readArrayB() {
|
public int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) { //componentDecoder可能为null
|
||||||
short bt = readShort();
|
short bt = readShort();
|
||||||
if (bt == Reader.SIGN_NULL) return bt;
|
if (bt == Reader.SIGN_NULL) return bt;
|
||||||
return (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
|
int rs = (bt & 0xffff) << 16 | ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
|
||||||
|
if (componentDecoder != null && componentDecoder != ByteSimpledCoder.instance) {
|
||||||
|
byte comval = readByte();
|
||||||
|
if (typevals != null) typevals[0] = comval;
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -202,13 +190,26 @@ public class BsonReader extends Reader {
|
|||||||
public final void readBlank() {
|
public final void readBlank() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int position() {
|
||||||
|
return this.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int readMemberContentLength(DeMember member, Decodeable decoder) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
||||||
*
|
*
|
||||||
|
* @param startPosition 起始位置
|
||||||
|
* @param contentLength 内容大小, 不确定的传-1
|
||||||
|
*
|
||||||
* @return 是否存在
|
* @return 是否存在
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final boolean hasNext() {
|
public boolean hasNext(int startPosition, int contentLength) {
|
||||||
byte b = readByte();
|
byte b = readByte();
|
||||||
if (b == SIGN_HASNEXT) return true;
|
if (b == SIGN_HASNEXT) return true;
|
||||||
if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT)
|
if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT)
|
||||||
@@ -248,6 +249,41 @@ public class BsonReader extends Reader {
|
|||||||
return content[++this.position];
|
return content[++this.position];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final byte[] readByteArray() {
|
||||||
|
int len = readArrayB(null, null, null);
|
||||||
|
int contentLength = -1;
|
||||||
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = readMemberContentLength(null, null);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
|
int size = 0;
|
||||||
|
byte[] data = new byte[8];
|
||||||
|
int startPosition = position();
|
||||||
|
while (hasNext(startPosition, contentLength)) {
|
||||||
|
if (size >= data.length) {
|
||||||
|
byte[] newdata = new byte[data.length + 4];
|
||||||
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
|
data = newdata;
|
||||||
|
}
|
||||||
|
data[size++] = readByte();
|
||||||
|
}
|
||||||
|
readArrayE();
|
||||||
|
byte[] newdata = new byte[size];
|
||||||
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
|
return newdata;
|
||||||
|
} else {
|
||||||
|
byte[] values = new byte[len];
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
values[i] = readByte();
|
||||||
|
}
|
||||||
|
readArrayE();
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char readChar() {
|
public char readChar() {
|
||||||
return (char) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position]));
|
return (char) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position]));
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package org.redkale.convert.bson;
|
|||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import org.redkale.convert.*;
|
import org.redkale.convert.*;
|
||||||
|
import org.redkale.convert.ext.ByteSimpledCoder;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,6 +99,7 @@ public class BsonWriter extends Writer {
|
|||||||
|
|
||||||
protected boolean recycle() {
|
protected boolean recycle() {
|
||||||
this.count = 0;
|
this.count = 0;
|
||||||
|
this.specify = null;
|
||||||
if (this.content.length > defaultSize) {
|
if (this.content.length > defaultSize) {
|
||||||
this.content = new byte[defaultSize];
|
this.content = new byte[defaultSize];
|
||||||
}
|
}
|
||||||
@@ -124,6 +126,22 @@ public class BsonWriter extends Writer {
|
|||||||
writeTo(value);
|
writeTo(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void writeByteArray(byte[] values) {
|
||||||
|
if (values == null) {
|
||||||
|
writeNull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
writeArrayB(values.length, null, values);
|
||||||
|
boolean flag = false;
|
||||||
|
for (byte v : values) {
|
||||||
|
if (flag) writeArrayMark();
|
||||||
|
writeByte(v);
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
writeArrayE();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void writeChar(final char value) {
|
public final void writeChar(final char value) {
|
||||||
writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF));
|
writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF));
|
||||||
@@ -166,10 +184,11 @@ public class BsonWriter extends Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void writeObjectB(Object obj) {
|
public final int writeObjectB(Object obj) {
|
||||||
super.writeObjectB(obj);
|
super.writeObjectB(obj);
|
||||||
writeSmallString("");
|
writeSmallString("");
|
||||||
writeShort(BsonReader.SIGN_OBJECTB);
|
writeShort(BsonReader.SIGN_OBJECTB);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -179,49 +198,11 @@ public class BsonWriter extends Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void writeFieldName(Attribute attribute) {
|
public final void writeFieldName(EnMember member) {
|
||||||
|
Attribute attribute = member.getAttribute();
|
||||||
writeByte(BsonReader.SIGN_HASNEXT);
|
writeByte(BsonReader.SIGN_HASNEXT);
|
||||||
writeSmallString(attribute.field());
|
writeSmallString(attribute.field());
|
||||||
byte typeval = 127; //字段的类型值
|
writeByte(BsonFactory.typeEnum(attribute.type()));
|
||||||
final Class type = attribute.type();
|
|
||||||
if (type == boolean.class || type == Boolean.class) {
|
|
||||||
typeval = 1;
|
|
||||||
} else if (type == byte.class || type == Byte.class) {
|
|
||||||
typeval = 2;
|
|
||||||
} else if (type == short.class || type == Short.class) {
|
|
||||||
typeval = 3;
|
|
||||||
} else if (type == char.class || type == Character.class) {
|
|
||||||
typeval = 4;
|
|
||||||
} else if (type == int.class || type == Integer.class) {
|
|
||||||
typeval = 5;
|
|
||||||
} else if (type == long.class || type == Long.class) {
|
|
||||||
typeval = 6;
|
|
||||||
} else if (type == float.class || type == Float.class) {
|
|
||||||
typeval = 7;
|
|
||||||
} else if (type == double.class || type == Double.class) {
|
|
||||||
typeval = 8;
|
|
||||||
} else if (type == String.class) {
|
|
||||||
typeval = 9;
|
|
||||||
} else if (type == boolean[].class || type == Boolean[].class) {
|
|
||||||
typeval = 101;
|
|
||||||
} else if (type == byte[].class || type == Byte[].class) {
|
|
||||||
typeval = 102;
|
|
||||||
} else if (type == short[].class || type == Short[].class) {
|
|
||||||
typeval = 103;
|
|
||||||
} else if (type == char[].class || type == Character[].class) {
|
|
||||||
typeval = 104;
|
|
||||||
} else if (type == int[].class || type == Integer[].class) {
|
|
||||||
typeval = 105;
|
|
||||||
} else if (type == long[].class || type == Long[].class) {
|
|
||||||
typeval = 106;
|
|
||||||
} else if (type == float[].class || type == Float[].class) {
|
|
||||||
typeval = 107;
|
|
||||||
} else if (type == double[].class || type == Double[].class) {
|
|
||||||
typeval = 108;
|
|
||||||
} else if (type == String[].class) {
|
|
||||||
typeval = 109;
|
|
||||||
}
|
|
||||||
writeByte(typeval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -266,8 +247,12 @@ public class BsonWriter extends Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void writeArrayB(int size) {
|
public final int writeArrayB(int size, Encodeable<Writer, Object> componentEncoder, Object obj) {
|
||||||
writeInt(size);
|
writeInt(size);
|
||||||
|
if (componentEncoder != null && componentEncoder != ByteSimpledCoder.instance) {
|
||||||
|
writeByte(BsonFactory.typeEnum(componentEncoder.getType()));
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -279,8 +264,11 @@ public class BsonWriter extends Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeMapB(int size) {
|
public int writeMapB(int size, Encodeable<Writer, Object> keyEncoder, Encodeable<Writer, Object> valueEncoder, Object obj) {
|
||||||
writeArrayB(size);
|
writeInt(size);
|
||||||
|
writeByte(BsonFactory.typeEnum(keyEncoder.getType()));
|
||||||
|
writeByte(BsonFactory.typeEnum(valueEncoder.getType()));
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
33
src/org/redkale/convert/bson/SkipArrayDecoder.java
Normal file
33
src/org/redkale/convert/bson/SkipArrayDecoder.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.convert.bson;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import org.redkale.convert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数组的反序列化操作类 <br>
|
||||||
|
* 对象数组的反序列化,不包含int[]、long[]这样的primitive class数组。 <br>
|
||||||
|
* 支持一定程度的泛型。 <br>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @param <T> 反解析的数组元素类型
|
||||||
|
*/
|
||||||
|
public class SkipArrayDecoder<T> extends ArrayDecoder<T> {
|
||||||
|
|
||||||
|
public SkipArrayDecoder(final ConvertFactory factory, final Type type) {
|
||||||
|
super(factory, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||||
|
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/org/redkale/convert/bson/SkipCollectionDecoder.java
Normal file
32
src/org/redkale/convert/bson/SkipCollectionDecoder.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.convert.bson;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import org.redkale.convert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection的反序列化操作类 <br>
|
||||||
|
* 支持一定程度的泛型。 <br>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @param <T> 反解析的集合元素类型
|
||||||
|
*/
|
||||||
|
public class SkipCollectionDecoder<T> extends CollectionDecoder<T> {
|
||||||
|
|
||||||
|
public SkipCollectionDecoder(final ConvertFactory factory, final Type type) {
|
||||||
|
super(factory, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||||
|
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/org/redkale/convert/bson/SkipMapDecoder.java
Normal file
38
src/org/redkale/convert/bson/SkipMapDecoder.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.convert.bson;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import org.redkale.convert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map的反序列化操作类 <br>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @param <K> Map key的数据类型
|
||||||
|
* @param <V> Map value的数据类型
|
||||||
|
*/
|
||||||
|
public class SkipMapDecoder<K, V> extends MapDecoder<K, V> {
|
||||||
|
|
||||||
|
public SkipMapDecoder(final ConvertFactory factory, final Type type) {
|
||||||
|
super(factory, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Decodeable<Reader, K> getKeyDecoder(Decodeable<Reader, K> decoder, byte[] typevals) {
|
||||||
|
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Decodeable<Reader, V> getValueDecoder(Decodeable<Reader, V> decoder, byte[] typevals) {
|
||||||
|
if (typevals != null) return BsonFactory.typeEnum(typevals[1]);
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/org/redkale/convert/bson/SkipStreamDecoder.java
Normal file
32
src/org/redkale/convert/bson/SkipStreamDecoder.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.convert.bson;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import org.redkale.convert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stream的反序列化操作类 <br>
|
||||||
|
* 支持一定程度的泛型。 <br>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @param <T> 反解析的集合元素类型
|
||||||
|
*/
|
||||||
|
public class SkipStreamDecoder<T> extends StreamDecoder<T> {
|
||||||
|
|
||||||
|
public SkipStreamDecoder(final ConvertFactory factory, final Type type) {
|
||||||
|
super(factory, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Decodeable<Reader, T> getComponentDecoder(Decodeable<Reader, T> decoder, byte[] typevals) {
|
||||||
|
if (typevals != null) return BsonFactory.typeEnum(typevals[0]);
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ public final class BigIntegerSimpledCoder<R extends Reader, W extends Writer> ex
|
|||||||
public static final BigIntegerSimpledCoder instance = new BigIntegerSimpledCoder();
|
public static final BigIntegerSimpledCoder instance = new BigIntegerSimpledCoder();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void convertTo(W out, BigInteger value) {
|
public void convertTo(W out, BigInteger value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
@@ -34,6 +35,7 @@ public final class BigIntegerSimpledCoder<R extends Reader, W extends Writer> ex
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public BigInteger convertFrom(R in) {
|
public BigInteger convertFrom(R in) {
|
||||||
byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in);
|
byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in);
|
||||||
return bytes == null ? null : new BigInteger(bytes);
|
return bytes == null ? null : new BigInteger(bytes);
|
||||||
|
|||||||
@@ -29,24 +29,31 @@ public final class BoolArraySimpledCoder<R extends Reader, W extends Writer> ext
|
|||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.writeArrayB(values.length);
|
if (out.writeArrayB(values.length, BoolSimpledCoder.instance, values) < 0) {
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
for (boolean v : values) {
|
for (boolean v : values) {
|
||||||
if (flag) out.writeArrayMark();
|
if (flag) out.writeArrayMark();
|
||||||
out.writeBoolean(v);
|
out.writeBoolean(v);
|
||||||
flag = true;
|
flag = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean[] convertFrom(R in) {
|
public boolean[] convertFrom(R in) {
|
||||||
int len = in.readArrayB();
|
int len = in.readArrayB(null, null, BoolSimpledCoder.instance);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(null, BoolSimpledCoder.instance);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
boolean[] data = new boolean[8];
|
boolean[] data = new boolean[8];
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
|
while (in.hasNext(startPosition, contentLength)) {
|
||||||
if (size >= data.length) {
|
if (size >= data.length) {
|
||||||
boolean[] newdata = new boolean[data.length + 4];
|
boolean[] newdata = new boolean[data.length + 4];
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import org.redkale.convert.Writer;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* byte[] 的SimpledCoder实现
|
* byte[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* 详情见: https://redkale.org
|
* 详情见: https://redkale.org
|
||||||
*
|
*
|
||||||
@@ -25,47 +25,12 @@ public final class ByteArraySimpledCoder<R extends Reader, W extends Writer> ext
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void convertTo(W out, byte[] values) {
|
public void convertTo(W out, byte[] values) {
|
||||||
if (values == null) {
|
out.writeByteArray(values);
|
||||||
out.writeNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.writeArrayB(values.length);
|
|
||||||
boolean flag = false;
|
|
||||||
for (byte v : values) {
|
|
||||||
if (flag) out.writeArrayMark();
|
|
||||||
out.writeByte(v);
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
out.writeArrayE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] convertFrom(R in) {
|
public byte[] convertFrom(R in) {
|
||||||
int len = in.readArrayB();
|
return in.readByteArray();
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
|
||||||
int size = 0;
|
|
||||||
byte[] data = new byte[8];
|
|
||||||
while (in.hasNext()) {
|
|
||||||
if (size >= data.length) {
|
|
||||||
byte[] newdata = new byte[data.length + 4];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
data = newdata;
|
|
||||||
}
|
|
||||||
data[size++] = in.readByte();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
byte[] newdata = new byte[size];
|
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
|
||||||
return newdata;
|
|
||||||
} else {
|
|
||||||
byte[] values = new byte[len];
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
values[i] = in.readByte();
|
|
||||||
}
|
|
||||||
in.readArrayE();
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,24 +30,31 @@ public final class ByteBufferSimpledCoder<R extends Reader, W extends Writer> ex
|
|||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.writeArrayB(value.remaining());
|
if (out.writeArrayB(value.remaining(), ByteSimpledCoder.instance, value) < 0) {
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
for (byte v : value.array()) {
|
for (byte v : value.array()) {
|
||||||
if (flag) out.writeArrayMark();
|
if (flag) out.writeArrayMark();
|
||||||
out.writeByte(v);
|
out.writeByte(v);
|
||||||
flag = true;
|
flag = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer convertFrom(R in) {
|
public ByteBuffer convertFrom(R in) {
|
||||||
int len = in.readArrayB();
|
int len = in.readArrayB(null, null, ByteSimpledCoder.instance);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(null, ByteSimpledCoder.instance);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
byte[] data = new byte[8];
|
byte[] data = new byte[8];
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
|
while (in.hasNext(startPosition, contentLength)) {
|
||||||
if (size >= data.length) {
|
if (size >= data.length) {
|
||||||
byte[] newdata = new byte[data.length + 4];
|
byte[] newdata = new byte[data.length + 4];
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* char[] 的SimpledCoder实现
|
* char[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: https://redkale.org
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
@@ -27,24 +29,31 @@ public final class CharArraySimpledCoder<R extends Reader, W extends Writer> ext
|
|||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.writeArrayB(values.length);
|
if (out.writeArrayB(values.length, CharSimpledCoder.instance, values) < 0) {
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
for (char v : values) {
|
for (char v : values) {
|
||||||
if (flag) out.writeArrayMark();
|
if (flag) out.writeArrayMark();
|
||||||
out.writeChar(v);
|
out.writeChar(v);
|
||||||
flag = true;
|
flag = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char[] convertFrom(R in) {
|
public char[] convertFrom(R in) {
|
||||||
int len = in.readArrayB();
|
int len = in.readArrayB(null, null, CharSimpledCoder.instance);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(null, CharSimpledCoder.instance);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
char[] data = new char[8];
|
char[] data = new char[8];
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
|
while (in.hasNext(startPosition, contentLength)) {
|
||||||
if (size >= data.length) {
|
if (size >= data.length) {
|
||||||
char[] newdata = new char[data.length + 4];
|
char[] newdata = new char[data.length + 4];
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public final class DLongSimpledCoder<R extends Reader, W extends Writer> extends
|
|||||||
public static final DLongSimpledCoder instance = new DLongSimpledCoder();
|
public static final DLongSimpledCoder instance = new DLongSimpledCoder();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void convertTo(final W out, final DLong value) {
|
public void convertTo(final W out, final DLong value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
@@ -36,6 +37,7 @@ public final class DLongSimpledCoder<R extends Reader, W extends Writer> extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public DLong convertFrom(R in) {
|
public DLong convertFrom(R in) {
|
||||||
byte[] bs = bsSimpledCoder.convertFrom(in);
|
byte[] bs = bsSimpledCoder.convertFrom(in);
|
||||||
if (bs == null) return null;
|
if (bs == null) return null;
|
||||||
|
|||||||
@@ -30,24 +30,31 @@ public final class DoubleArraySimpledCoder<R extends Reader, W extends Writer> e
|
|||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.writeArrayB(values.length);
|
if (out.writeArrayB(values.length, DoubleSimpledCoder.instance, values) < 0) {
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
for (double v : values) {
|
for (double v : values) {
|
||||||
if (flag) out.writeArrayMark();
|
if (flag) out.writeArrayMark();
|
||||||
out.writeDouble(v);
|
out.writeDouble(v);
|
||||||
flag = true;
|
flag = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double[] convertFrom(R in) {
|
public double[] convertFrom(R in) {
|
||||||
int len = in.readArrayB();
|
int len = in.readArrayB(null, null, DoubleSimpledCoder.instance);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(null, DoubleSimpledCoder.instance);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
double[] data = new double[8];
|
double[] data = new double[8];
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
|
while (in.hasNext(startPosition, contentLength)) {
|
||||||
if (size >= data.length) {
|
if (size >= data.length) {
|
||||||
double[] newdata = new double[data.length + 4];
|
double[] newdata = new double[data.length + 4];
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
@@ -74,6 +81,7 @@ public final class DoubleArraySimpledCoder<R extends Reader, W extends Writer> e
|
|||||||
public static final DoubleStreamSimpledCoder instance = new DoubleStreamSimpledCoder();
|
public static final DoubleStreamSimpledCoder instance = new DoubleStreamSimpledCoder();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void convertTo(W out, DoubleStream values) {
|
public void convertTo(W out, DoubleStream values) {
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
@@ -83,6 +91,7 @@ public final class DoubleArraySimpledCoder<R extends Reader, W extends Writer> e
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public DoubleStream convertFrom(R in) {
|
public DoubleStream convertFrom(R in) {
|
||||||
double[] value = DoubleArraySimpledCoder.instance.convertFrom(in);
|
double[] value = DoubleArraySimpledCoder.instance.convertFrom(in);
|
||||||
return value == null ? null : DoubleStream.of(value);
|
return value == null ? null : DoubleStream.of(value);
|
||||||
|
|||||||
@@ -45,4 +45,8 @@ public final class EnumSimpledCoder<R extends Reader, W extends Writer, E extend
|
|||||||
return (E) Enum.valueOf(type, value);
|
return (E) Enum.valueOf(type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<E> getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* float[] 的SimpledCoder实现
|
* float[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: https://redkale.org
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
@@ -27,24 +29,31 @@ public final class FloatArraySimpledCoder<R extends Reader, W extends Writer> ex
|
|||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.writeArrayB(values.length);
|
if (out.writeArrayB(values.length, FloatSimpledCoder.instance, values) < 0) {
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
for (float v : values) {
|
for (float v : values) {
|
||||||
if (flag) out.writeArrayMark();
|
if (flag) out.writeArrayMark();
|
||||||
out.writeFloat(v);
|
out.writeFloat(v);
|
||||||
flag = true;
|
flag = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float[] convertFrom(R in) {
|
public float[] convertFrom(R in) {
|
||||||
int len = in.readArrayB();
|
int len = in.readArrayB(null, null, FloatSimpledCoder.instance);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(null, FloatSimpledCoder.instance);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
float[] data = new float[8];
|
float[] data = new float[8];
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
|
while (in.hasNext(startPosition, contentLength)) {
|
||||||
if (size >= data.length) {
|
if (size >= data.length) {
|
||||||
float[] newdata = new float[data.length + 4];
|
float[] newdata = new float[data.length + 4];
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
|
|||||||
@@ -30,24 +30,31 @@ public final class IntArraySimpledCoder<R extends Reader, W extends Writer> exte
|
|||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.writeArrayB(values.length);
|
if (out.writeArrayB(values.length, IntSimpledCoder.instance, values) < 0) {
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
for (int v : values) {
|
for (int v : values) {
|
||||||
if (flag) out.writeArrayMark();
|
if (flag) out.writeArrayMark();
|
||||||
out.writeInt(v);
|
out.writeInt(v);
|
||||||
flag = true;
|
flag = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] convertFrom(R in) {
|
public int[] convertFrom(R in) {
|
||||||
int len = in.readArrayB();
|
int len = in.readArrayB(null, null, IntSimpledCoder.instance);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(null, IntSimpledCoder.instance);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int[] data = new int[8];
|
int[] data = new int[8];
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
|
while (in.hasNext(startPosition, contentLength)) {
|
||||||
if (size >= data.length) {
|
if (size >= data.length) {
|
||||||
int[] newdata = new int[data.length + 4];
|
int[] newdata = new int[data.length + 4];
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
@@ -74,6 +81,7 @@ public final class IntArraySimpledCoder<R extends Reader, W extends Writer> exte
|
|||||||
public static final IntStreamSimpledCoder instance = new IntStreamSimpledCoder();
|
public static final IntStreamSimpledCoder instance = new IntStreamSimpledCoder();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void convertTo(W out, IntStream values) {
|
public void convertTo(W out, IntStream values) {
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
@@ -83,6 +91,7 @@ public final class IntArraySimpledCoder<R extends Reader, W extends Writer> exte
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public IntStream convertFrom(R in) {
|
public IntStream convertFrom(R in) {
|
||||||
int[] value = IntArraySimpledCoder.instance.convertFrom(in);
|
int[] value = IntArraySimpledCoder.instance.convertFrom(in);
|
||||||
return value == null ? null : IntStream.of(value);
|
return value == null ? null : IntStream.of(value);
|
||||||
|
|||||||
@@ -30,24 +30,31 @@ public final class LongArraySimpledCoder<R extends Reader, W extends Writer> ext
|
|||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.writeArrayB(values.length);
|
if (out.writeArrayB(values.length, LongSimpledCoder.instance, values) < 0) {
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
for (long v : values) {
|
for (long v : values) {
|
||||||
if (flag) out.writeArrayMark();
|
if (flag) out.writeArrayMark();
|
||||||
out.writeLong(v);
|
out.writeLong(v);
|
||||||
flag = true;
|
flag = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long[] convertFrom(R in) {
|
public long[] convertFrom(R in) {
|
||||||
int len = in.readArrayB();
|
int len = in.readArrayB(null, null, LongSimpledCoder.instance);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(null, LongSimpledCoder.instance);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
long[] data = new long[8];
|
long[] data = new long[8];
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
|
while (in.hasNext(startPosition, contentLength)) {
|
||||||
if (size >= data.length) {
|
if (size >= data.length) {
|
||||||
long[] newdata = new long[data.length + 4];
|
long[] newdata = new long[data.length + 4];
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
@@ -74,6 +81,7 @@ public final class LongArraySimpledCoder<R extends Reader, W extends Writer> ext
|
|||||||
public static final LongStreamSimpledCoder instance = new LongStreamSimpledCoder();
|
public static final LongStreamSimpledCoder instance = new LongStreamSimpledCoder();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void convertTo(W out, LongStream values) {
|
public void convertTo(W out, LongStream values) {
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
@@ -83,6 +91,7 @@ public final class LongArraySimpledCoder<R extends Reader, W extends Writer> ext
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public LongStream convertFrom(R in) {
|
public LongStream convertFrom(R in) {
|
||||||
long[] value = LongArraySimpledCoder.instance.convertFrom(in);
|
long[] value = LongArraySimpledCoder.instance.convertFrom(in);
|
||||||
return value == null ? null : LongStream.of(value);
|
return value == null ? null : LongStream.of(value);
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import org.redkale.convert.Writer;
|
|||||||
/**
|
/**
|
||||||
* short[] 的SimpledCoder实现
|
* short[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: https://redkale.org
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
@@ -27,24 +29,31 @@ public final class ShortArraySimpledCoder<R extends Reader, W extends Writer> ex
|
|||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.writeArrayB(values.length);
|
if (out.writeArrayB(values.length, ShortSimpledCoder.instance, values) < 0) {
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
for (short v : values) {
|
for (short v : values) {
|
||||||
if (flag) out.writeArrayMark();
|
if (flag) out.writeArrayMark();
|
||||||
out.writeShort(v);
|
out.writeShort(v);
|
||||||
flag = true;
|
flag = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short[] convertFrom(R in) {
|
public short[] convertFrom(R in) {
|
||||||
int len = in.readArrayB();
|
int len = in.readArrayB(null, null, ShortSimpledCoder.instance);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(null, ShortSimpledCoder.instance);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
short[] data = new short[8];
|
short[] data = new short[8];
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
|
while (in.hasNext(startPosition, contentLength)) {
|
||||||
if (size >= data.length) {
|
if (size >= data.length) {
|
||||||
short[] newdata = new short[data.length + 4];
|
short[] newdata = new short[data.length + 4];
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.convert.ext;
|
package org.redkale.convert.ext;
|
||||||
|
|
||||||
import org.redkale.convert.Reader;
|
import org.redkale.convert.*;
|
||||||
import org.redkale.convert.SimpledCoder;
|
|
||||||
import org.redkale.convert.Writer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String[] 的SimpledCoder实现
|
* String[] 的SimpledCoder实现
|
||||||
*
|
*
|
||||||
* <p> 详情见: https://redkale.org
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
* @param <R> Reader输入的子类型
|
* @param <R> Reader输入的子类型
|
||||||
* @param <W> Writer输出的子类型
|
* @param <W> Writer输出的子类型
|
||||||
@@ -27,24 +27,35 @@ public final class StringArraySimpledCoder<R extends Reader, W extends Writer> e
|
|||||||
out.writeNull();
|
out.writeNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
out.writeArrayB(values.length);
|
if (out.writeArrayB(values.length, StringSimpledCoder.instance, values) < 0) {
|
||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
for (String v : values) {
|
for (String v : values) {
|
||||||
if (flag) out.writeArrayMark();
|
if (flag) out.writeArrayMark();
|
||||||
out.writeString(v);
|
out.writeString(v);
|
||||||
flag = true;
|
flag = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.writeArrayE();
|
out.writeArrayE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] convertFrom(R in) {
|
public String[] convertFrom(R in) {
|
||||||
int len = in.readArrayB();
|
return convertFrom(in, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] convertFrom(R in, DeMember member) {
|
||||||
|
int len = in.readArrayB(member, null, StringSimpledCoder.instance);
|
||||||
|
int contentLength = -1;
|
||||||
if (len == Reader.SIGN_NULL) return null;
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = in.readMemberContentLength(null, StringSimpledCoder.instance);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
if (len == Reader.SIGN_NOLENGTH) {
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
String[] data = new String[8];
|
String[] data = new String[8];
|
||||||
while (in.hasNext()) {
|
int startPosition = in.position();
|
||||||
|
while (in.hasNext(startPosition, contentLength)) {
|
||||||
if (size >= data.length) {
|
if (size >= data.length) {
|
||||||
String[] newdata = new String[data.length + 4];
|
String[] newdata = new String[data.length + 4];
|
||||||
System.arraycopy(data, 0, newdata, 0, size);
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
|
|||||||
@@ -126,21 +126,39 @@ public class JsonByteBufferReader extends JsonReader {
|
|||||||
if (ch == '{') return "";
|
if (ch == '{') return "";
|
||||||
if (ch == 'n' && nextChar() == 'u' && nextChar() == 'l' && nextChar() == 'l') return null;
|
if (ch == 'n' && nextChar() == 'u' && nextChar() == 'l' && nextChar() == 'l') return null;
|
||||||
if (ch == 'N' && nextChar() == 'U' && nextChar() == 'L' && nextChar() == 'L') return null;
|
if (ch == 'N' && nextChar() == 'U' && nextChar() == 'L' && nextChar() == 'L') return null;
|
||||||
throw new ConvertException("a json object text must begin with '{' (position = " + position + ") but '" + ch + "'");
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(ch);
|
||||||
|
char one;
|
||||||
|
try {
|
||||||
|
while ((one = nextChar()) != 0) sb.append(one);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
throw new ConvertException("a json object text must begin with '{' (position = " + position + ") but '" + ch + "' in (" + sb + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断下一个非空白字符是否为[
|
* 判断下一个非空白字符是否为[
|
||||||
*
|
*
|
||||||
|
* @param member DeMember
|
||||||
|
* @param typevals byte[]
|
||||||
|
* @param decoder Decodeable
|
||||||
|
*
|
||||||
* @return SIGN_NOLENGTH 或 SIGN_NULL
|
* @return SIGN_NOLENGTH 或 SIGN_NULL
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final int readArrayB() {
|
public final int readArrayB(DeMember member, byte[] typevals, Decodeable decoder) {
|
||||||
char ch = nextGoodChar();
|
char ch = nextGoodChar();
|
||||||
if (ch == '[' || ch == '{') return SIGN_NOLENGTH;
|
if (ch == '[' || ch == '{') return SIGN_NOLENGTH;
|
||||||
if (ch == 'n' && nextChar() == 'u' && nextChar() == 'l' && nextChar() == 'l') return SIGN_NULL;
|
if (ch == 'n' && nextChar() == 'u' && nextChar() == 'l' && nextChar() == 'l') return SIGN_NULL;
|
||||||
if (ch == 'N' && nextChar() == 'U' && nextChar() == 'L' && nextChar() == 'L') return SIGN_NULL;
|
if (ch == 'N' && nextChar() == 'U' && nextChar() == 'L' && nextChar() == 'L') return SIGN_NULL;
|
||||||
throw new ConvertException("a json array text must begin with '[' (position = " + position + ") but '" + ch + "'");
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(ch);
|
||||||
|
char one;
|
||||||
|
try {
|
||||||
|
while ((one = nextChar()) != 0) sb.append(one);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
throw new ConvertException("a json array text must begin with '[' (position = " + position + ") but '" + ch + "' in (" + sb + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,16 +168,26 @@ public class JsonByteBufferReader extends JsonReader {
|
|||||||
public final void readBlank() {
|
public final void readBlank() {
|
||||||
char ch = nextGoodChar();
|
char ch = nextGoodChar();
|
||||||
if (ch == ':') return;
|
if (ch == ':') return;
|
||||||
throw new ConvertException("expected a ':' but '" + ch + "'(position = " + position + ")");
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(ch);
|
||||||
|
char one;
|
||||||
|
try {
|
||||||
|
while ((one = nextChar()) != 0) sb.append(one);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
throw new ConvertException("expected a ':' but '" + ch + "'(position = " + position + ") in (" + sb + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
||||||
*
|
*
|
||||||
|
* @param startPosition 起始位置
|
||||||
|
* @param contentLength 内容大小, 不确定的传-1
|
||||||
|
*
|
||||||
* @return 是否存在
|
* @return 是否存在
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final boolean hasNext() {
|
public boolean hasNext(int startPosition, int contentLength) {
|
||||||
char ch = nextGoodChar();
|
char ch = nextGoodChar();
|
||||||
if (ch == ',') return true;
|
if (ch == ',') return true;
|
||||||
if (ch == '}' || ch == ']' || ch == 0) return false;
|
if (ch == '}' || ch == ']' || ch == 0) return false;
|
||||||
@@ -272,8 +300,10 @@ public class JsonByteBufferReader extends JsonReader {
|
|||||||
@Override
|
@Override
|
||||||
public final int readInt() {
|
public final int readInt() {
|
||||||
char firstchar = nextGoodChar();
|
char firstchar = nextGoodChar();
|
||||||
|
boolean quote = false;
|
||||||
if (firstchar == '"' || firstchar == '\'') {
|
if (firstchar == '"' || firstchar == '\'') {
|
||||||
firstchar = nextChar();
|
quote = true;
|
||||||
|
firstchar = nextGoodChar();
|
||||||
if (firstchar == '"' || firstchar == '\'') return 0;
|
if (firstchar == '"' || firstchar == '\'') return 0;
|
||||||
}
|
}
|
||||||
int value = 0;
|
int value = 0;
|
||||||
@@ -288,6 +318,7 @@ public class JsonByteBufferReader extends JsonReader {
|
|||||||
if (ch >= '0' && ch <= '9') {
|
if (ch >= '0' && ch <= '9') {
|
||||||
value = (value << 3) + (value << 1) + (ch - '0');
|
value = (value << 3) + (value << 1) + (ch - '0');
|
||||||
} else if (ch == '"' || ch == '\'') {
|
} else if (ch == '"' || ch == '\'') {
|
||||||
|
} else if (quote && ch <= ' ') {
|
||||||
} else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') {
|
} else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') {
|
||||||
backChar(ch);
|
backChar(ch);
|
||||||
break;
|
break;
|
||||||
@@ -306,8 +337,10 @@ public class JsonByteBufferReader extends JsonReader {
|
|||||||
@Override
|
@Override
|
||||||
public final long readLong() {
|
public final long readLong() {
|
||||||
char firstchar = nextGoodChar();
|
char firstchar = nextGoodChar();
|
||||||
|
boolean quote = false;
|
||||||
if (firstchar == '"' || firstchar == '\'') {
|
if (firstchar == '"' || firstchar == '\'') {
|
||||||
firstchar = nextChar();
|
quote = true;
|
||||||
|
firstchar = nextGoodChar();
|
||||||
if (firstchar == '"' || firstchar == '\'') return 0L;
|
if (firstchar == '"' || firstchar == '\'') return 0L;
|
||||||
}
|
}
|
||||||
long value = 0;
|
long value = 0;
|
||||||
@@ -322,6 +355,7 @@ public class JsonByteBufferReader extends JsonReader {
|
|||||||
if (ch >= '0' && ch <= '9') {
|
if (ch >= '0' && ch <= '9') {
|
||||||
value = (value << 3) + (value << 1) + (ch - '0');
|
value = (value << 3) + (value << 1) + (ch - '0');
|
||||||
} else if (ch == '"' || ch == '\'') {
|
} else if (ch == '"' || ch == '\'') {
|
||||||
|
} else if (quote && ch <= ' ') {
|
||||||
} else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') {
|
} else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') {
|
||||||
backChar(ch);
|
backChar(ch);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ import org.redkale.util.*;
|
|||||||
*/
|
*/
|
||||||
public class JsonByteBufferWriter extends JsonWriter {
|
public class JsonByteBufferWriter extends JsonWriter {
|
||||||
|
|
||||||
protected static final Charset UTF8 = Charset.forName("UTF-8");
|
|
||||||
|
|
||||||
protected Charset charset;
|
protected Charset charset;
|
||||||
|
|
||||||
private final Supplier<ByteBuffer> supplier;
|
private final Supplier<ByteBuffer> supplier;
|
||||||
@@ -38,7 +36,7 @@ public class JsonByteBufferWriter extends JsonWriter {
|
|||||||
|
|
||||||
protected JsonByteBufferWriter(boolean tiny, Charset charset, Supplier<ByteBuffer> supplier) {
|
protected JsonByteBufferWriter(boolean tiny, Charset charset, Supplier<ByteBuffer> supplier) {
|
||||||
this.tiny = tiny;
|
this.tiny = tiny;
|
||||||
this.charset = UTF8.equals(charset) ? null : charset;
|
this.charset = StandardCharsets.UTF_8.equals(charset) ? null : charset;
|
||||||
this.supplier = supplier;
|
this.supplier = supplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +49,7 @@ public class JsonByteBufferWriter extends JsonWriter {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean recycle() {
|
protected boolean recycle() {
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
|
this.specify = null;
|
||||||
this.charset = null;
|
this.charset = null;
|
||||||
this.buffers = null;
|
this.buffers = null;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
return writerPool.get().tiny(tiny);
|
return writerPool.get().tiny(tiny);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void offerJsonWriter(final JsonWriter out) {
|
public void offerJsonWriter(final JsonWriter writer) {
|
||||||
if (out != null) writerPool.accept(out);
|
if (writer != null) writerPool.accept(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------ convertFrom -----------------------------------------------------------
|
//------------------------------ convertFrom -----------------------------------------------------------
|
||||||
@@ -139,20 +139,21 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
public String convertTo(final Type type, final Object value) {
|
public String convertTo(final Type type, final Object value) {
|
||||||
if (type == null) return null;
|
if (type == null) return null;
|
||||||
if (value == null) return "null";
|
if (value == null) return "null";
|
||||||
final JsonWriter out = writerPool.get().tiny(tiny);
|
final JsonWriter writer = writerPool.get().tiny(tiny);
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
writer.specify(type);
|
||||||
String result = out.toString();
|
factory.loadEncoder(type).convertTo(writer, value);
|
||||||
writerPool.accept(out);
|
String result = writer.toString();
|
||||||
|
writerPool.accept(writer);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String convertMapTo(final Object... values) {
|
public String convertMapTo(final Object... values) {
|
||||||
if (values == null) return "null";
|
if (values == null) return "null";
|
||||||
final JsonWriter out = writerPool.get().tiny(tiny);
|
final JsonWriter writer = writerPool.get().tiny(tiny);
|
||||||
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(out, values);
|
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(writer, values);
|
||||||
String result = out.toString();
|
String result = writer.toString();
|
||||||
writerPool.accept(out);
|
writerPool.accept(writer);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +171,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
new JsonStreamWriter(tiny, out).writeNull();
|
new JsonStreamWriter(tiny, out).writeNull();
|
||||||
} else {
|
} else {
|
||||||
final JsonWriter writer = writerPool.get().tiny(tiny);
|
final JsonWriter writer = writerPool.get().tiny(tiny);
|
||||||
|
writer.specify(type);
|
||||||
factory.loadEncoder(type).convertTo(writer, value);
|
factory.loadEncoder(type).convertTo(writer, value);
|
||||||
byte[] bs = writer.toBytes();
|
byte[] bs = writer.toBytes();
|
||||||
writerPool.accept(writer);
|
writerPool.accept(writer);
|
||||||
@@ -216,6 +218,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
} else {
|
} else {
|
||||||
|
out.specify(type);
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
factory.loadEncoder(type).convertTo(out, value);
|
||||||
}
|
}
|
||||||
return out.toBuffers();
|
return out.toBuffers();
|
||||||
@@ -246,6 +249,7 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
if (value == null) {
|
if (value == null) {
|
||||||
writer.writeNull();
|
writer.writeNull();
|
||||||
} else {
|
} else {
|
||||||
|
writer.specify(type);
|
||||||
factory.loadEncoder(type).convertTo(writer, value);
|
factory.loadEncoder(type).convertTo(writer, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,14 +269,15 @@ public final class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
|
|
||||||
public JsonWriter convertToWriter(final Type type, final Object value) {
|
public JsonWriter convertToWriter(final Type type, final Object value) {
|
||||||
if (type == null) return null;
|
if (type == null) return null;
|
||||||
final JsonWriter out = writerPool.get().tiny(tiny);
|
final JsonWriter writer = writerPool.get().tiny(tiny);
|
||||||
factory.loadEncoder(type).convertTo(out, value);
|
writer.specify(type);
|
||||||
return out;
|
factory.loadEncoder(type).convertTo(writer, value);
|
||||||
|
return writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonWriter convertMapToWriter(final Object... values) {
|
public JsonWriter convertMapToWriter(final Object... values) {
|
||||||
final JsonWriter out = writerPool.get().tiny(tiny);
|
final JsonWriter writer = writerPool.get().tiny(tiny);
|
||||||
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(out, values);
|
((AnyEncoder) factory.getAnyEncoder()).convertMapTo(writer, values);
|
||||||
return out;
|
return writer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,4 +85,9 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
|
|||||||
public boolean isReversible() {
|
public boolean isReversible() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFieldSort() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ public class JsonReader extends Reader {
|
|||||||
@Override
|
@Override
|
||||||
public String readObjectB(final Class clazz) {
|
public String readObjectB(final Class clazz) {
|
||||||
this.fieldIndex = 0; //必须要重置为0
|
this.fieldIndex = 0; //必须要重置为0
|
||||||
|
if (this.text.length == 0) return null;
|
||||||
char ch = this.text[++this.position];
|
char ch = this.text[++this.position];
|
||||||
if (ch == '{') return "";
|
if (ch == '{') return "";
|
||||||
if (ch <= ' ') {
|
if (ch <= ' ') {
|
||||||
@@ -189,11 +190,16 @@ public class JsonReader extends Reader {
|
|||||||
/**
|
/**
|
||||||
* 判断下一个非空白字符是否为{
|
* 判断下一个非空白字符是否为{
|
||||||
*
|
*
|
||||||
|
* @param member DeMember
|
||||||
|
* @param typevals byte[]
|
||||||
|
* @param keyDecoder Decodeable
|
||||||
|
* @param valuedecoder Decodeable
|
||||||
|
*
|
||||||
* @return SIGN_NOLENGTH 或 SIGN_NULL
|
* @return SIGN_NOLENGTH 或 SIGN_NULL
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final int readMapB() {
|
public final int readMapB(DeMember member, byte[] typevals, Decodeable keyDecoder, Decodeable valuedecoder) {
|
||||||
return readArrayB();
|
return readArrayB(member, typevals, keyDecoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -203,10 +209,15 @@ public class JsonReader extends Reader {
|
|||||||
/**
|
/**
|
||||||
* 判断下一个非空白字符是否为[
|
* 判断下一个非空白字符是否为[
|
||||||
*
|
*
|
||||||
|
* @param member DeMember
|
||||||
|
* @param typevals byte[]
|
||||||
|
* @param componentDecoder Decodeable
|
||||||
|
*
|
||||||
* @return SIGN_NOLENGTH 或 SIGN_NULL
|
* @return SIGN_NOLENGTH 或 SIGN_NULL
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int readArrayB() {
|
public int readArrayB(DeMember member, byte[] typevals, Decodeable componentDecoder) {
|
||||||
|
if (this.text.length == 0) return SIGN_NULL;
|
||||||
char ch = this.text[++this.position];
|
char ch = this.text[++this.position];
|
||||||
if (ch == '[') return SIGN_NOLENGTH;
|
if (ch == '[') return SIGN_NOLENGTH;
|
||||||
if (ch == '{') return SIGN_NOLENGTH;
|
if (ch == '{') return SIGN_NOLENGTH;
|
||||||
@@ -244,13 +255,26 @@ public class JsonReader extends Reader {
|
|||||||
throw new ConvertException("'" + new String(text) + "'expected a ':' but '" + ch + "'(position = " + position + ") in (" + new String(this.text) + ")");
|
throw new ConvertException("'" + new String(text) + "'expected a ':' but '" + ch + "'(position = " + position + ") in (" + new String(this.text) + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int position() {
|
||||||
|
return this.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int readMemberContentLength(DeMember member, Decodeable decoder) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
|
||||||
*
|
*
|
||||||
|
* @param startPosition 起始位置
|
||||||
|
* @param contentLength 内容大小, 不确定的传-1
|
||||||
|
*
|
||||||
* @return 是否存在
|
* @return 是否存在
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext(int startPosition, int contentLength) {
|
||||||
char ch = this.text[++this.position];
|
char ch = this.text[++this.position];
|
||||||
if (ch == ',') return true;
|
if (ch == ',') return true;
|
||||||
if (ch == '}' || ch == ']') return false;
|
if (ch == '}' || ch == ']') return false;
|
||||||
@@ -314,7 +338,7 @@ public class JsonReader extends Reader {
|
|||||||
}
|
}
|
||||||
this.position = currpos - 1;
|
this.position = currpos - 1;
|
||||||
if (len == 4 && text0[start] == 'n' && text0[start + 1] == 'u' && text0[start + 2] == 'l' && text0[start + 3] == 'l') return null;
|
if (len == 4 && text0[start] == 'n' && text0[start + 1] == 'u' && text0[start + 2] == 'l' && text0[start + 3] == 'l') return null;
|
||||||
return new String(text0, start, len);
|
return new String(text0, start, len == eof ? (len + 1) : len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,8 +359,16 @@ public class JsonReader extends Reader {
|
|||||||
if (firstchar > ' ') break;
|
if (firstchar > ' ') break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
boolean quote = false;
|
||||||
if (firstchar == '"' || firstchar == '\'') {
|
if (firstchar == '"' || firstchar == '\'') {
|
||||||
|
quote = true;
|
||||||
firstchar = text0[++currpos];
|
firstchar = text0[++currpos];
|
||||||
|
if (firstchar <= ' ') {
|
||||||
|
for (;;) {
|
||||||
|
firstchar = text0[++currpos];
|
||||||
|
if (firstchar > ' ') break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (firstchar == '"' || firstchar == '\'') {
|
if (firstchar == '"' || firstchar == '\'') {
|
||||||
this.position = currpos;
|
this.position = currpos;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -352,7 +384,8 @@ public class JsonReader extends Reader {
|
|||||||
if (currpos == eof) break;
|
if (currpos == eof) break;
|
||||||
char ch = text0[++currpos];
|
char ch = text0[++currpos];
|
||||||
int val = digits[ch];
|
int val = digits[ch];
|
||||||
if (val == -3) break;
|
if (quote && val == -3) continue;
|
||||||
|
if (val <= -3) break;
|
||||||
if (val == -1) throw new ConvertException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")");
|
if (val == -1) throw new ConvertException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")");
|
||||||
if (val != -2) value = value * 10 + val;
|
if (val != -2) value = value * 10 + val;
|
||||||
}
|
}
|
||||||
@@ -377,8 +410,16 @@ public class JsonReader extends Reader {
|
|||||||
if (firstchar > ' ') break;
|
if (firstchar > ' ') break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
boolean quote = false;
|
||||||
if (firstchar == '"' || firstchar == '\'') {
|
if (firstchar == '"' || firstchar == '\'') {
|
||||||
|
quote = true;
|
||||||
firstchar = text0[++currpos];
|
firstchar = text0[++currpos];
|
||||||
|
if (firstchar <= ' ') {
|
||||||
|
for (;;) {
|
||||||
|
firstchar = text0[++currpos];
|
||||||
|
if (firstchar > ' ') break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (firstchar == '"' || firstchar == '\'') {
|
if (firstchar == '"' || firstchar == '\'') {
|
||||||
this.position = currpos;
|
this.position = currpos;
|
||||||
return 0L;
|
return 0L;
|
||||||
@@ -394,7 +435,8 @@ public class JsonReader extends Reader {
|
|||||||
if (currpos == eof) break;
|
if (currpos == eof) break;
|
||||||
char ch = text0[++currpos];
|
char ch = text0[++currpos];
|
||||||
int val = digits[ch];
|
int val = digits[ch];
|
||||||
if (val == -3) break;
|
if (quote && val == -3) continue;
|
||||||
|
if (val <= -3) break;
|
||||||
if (val == -1) throw new ConvertException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")");
|
if (val == -1) throw new ConvertException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")");
|
||||||
if (val != -2) value = value * 10 + val;
|
if (val != -2) value = value * 10 + val;
|
||||||
}
|
}
|
||||||
@@ -435,6 +477,41 @@ public class JsonReader extends Reader {
|
|||||||
return (byte) readInt();
|
return (byte) readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final byte[] readByteArray() {
|
||||||
|
int len = readArrayB(null, null, null);
|
||||||
|
int contentLength = -1;
|
||||||
|
if (len == Reader.SIGN_NULL) return null;
|
||||||
|
if (len == Reader.SIGN_NOLENBUTBYTES) {
|
||||||
|
contentLength = readMemberContentLength(null, null);
|
||||||
|
len = Reader.SIGN_NOLENGTH;
|
||||||
|
}
|
||||||
|
if (len == Reader.SIGN_NOLENGTH) {
|
||||||
|
int size = 0;
|
||||||
|
byte[] data = new byte[8];
|
||||||
|
int startPosition = position();
|
||||||
|
while (hasNext(startPosition, contentLength)) {
|
||||||
|
if (size >= data.length) {
|
||||||
|
byte[] newdata = new byte[data.length + 4];
|
||||||
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
|
data = newdata;
|
||||||
|
}
|
||||||
|
data[size++] = readByte();
|
||||||
|
}
|
||||||
|
readArrayE();
|
||||||
|
byte[] newdata = new byte[size];
|
||||||
|
System.arraycopy(data, 0, newdata, 0, size);
|
||||||
|
return newdata;
|
||||||
|
} else {
|
||||||
|
byte[] values = new byte[len];
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
values[i] = readByte();
|
||||||
|
}
|
||||||
|
readArrayE();
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final char readChar() {
|
public final char readChar() {
|
||||||
return (char) readInt();
|
return (char) readInt();
|
||||||
@@ -448,6 +525,7 @@ public class JsonReader extends Reader {
|
|||||||
@Override
|
@Override
|
||||||
public final float readFloat() {
|
public final float readFloat() {
|
||||||
String chars = readSmallString();
|
String chars = readSmallString();
|
||||||
|
if (chars != null) chars = chars.trim();
|
||||||
if (chars == null || chars.isEmpty()) return 0.f;
|
if (chars == null || chars.isEmpty()) return 0.f;
|
||||||
return Float.parseFloat(chars);
|
return Float.parseFloat(chars);
|
||||||
}
|
}
|
||||||
@@ -455,6 +533,7 @@ public class JsonReader extends Reader {
|
|||||||
@Override
|
@Override
|
||||||
public final double readDouble() {
|
public final double readDouble() {
|
||||||
String chars = readSmallString();
|
String chars = readSmallString();
|
||||||
|
if (chars != null) chars = chars.trim();
|
||||||
if (chars == null || chars.isEmpty()) return 0.0;
|
if (chars == null || chars.isEmpty()) return 0.0;
|
||||||
return Double.parseDouble(chars);
|
return Double.parseDouble(chars);
|
||||||
}
|
}
|
||||||
@@ -590,7 +669,8 @@ public class JsonReader extends Reader {
|
|||||||
digits[i] = i - 'A' + 10;
|
digits[i] = i - 'A' + 10;
|
||||||
}
|
}
|
||||||
digits['"'] = digits['\''] = -2; //-2 跳过
|
digits['"'] = digits['\''] = -2; //-2 跳过
|
||||||
digits[','] = digits['}'] = digits[']'] = digits[' '] = digits['\t'] = digits['\r'] = digits['\n'] = digits[':'] = -3; //-3退出
|
digits[' '] = digits['\t'] = digits['\r'] = digits['\n'] = -3; //-3可能跳过
|
||||||
|
digits[','] = digits['}'] = digits[']'] = digits[':'] = -4; //-4退出
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
package org.redkale.convert.json;
|
package org.redkale.convert.json;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import org.redkale.convert.Writer;
|
import org.redkale.convert.*;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,6 +99,7 @@ public class JsonWriter extends Writer {
|
|||||||
|
|
||||||
protected boolean recycle() {
|
protected boolean recycle() {
|
||||||
this.count = 0;
|
this.count = 0;
|
||||||
|
this.specify = null;
|
||||||
if (this.content.length > defaultSize) {
|
if (this.content.length > defaultSize) {
|
||||||
this.content = new char[defaultSize];
|
this.content = new char[defaultSize];
|
||||||
}
|
}
|
||||||
@@ -156,9 +157,9 @@ public class JsonWriter extends Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void writeFieldName(Attribute attribute) {
|
public final void writeFieldName(EnMember member) {
|
||||||
if (this.comma) writeTo(',');
|
if (this.comma) writeTo(',');
|
||||||
writeTo(true, attribute.field());
|
writeTo(true, member.getAttribute().field());
|
||||||
writeTo(':');
|
writeTo(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +188,22 @@ public class JsonWriter extends Writer {
|
|||||||
writeInt(value);
|
writeInt(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void writeByteArray(byte[] values) {
|
||||||
|
if (values == null) {
|
||||||
|
writeNull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
writeArrayB(values.length, null, values);
|
||||||
|
boolean flag = false;
|
||||||
|
for (byte v : values) {
|
||||||
|
if (flag) writeArrayMark();
|
||||||
|
writeByte(v);
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
writeArrayE();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void writeChar(char value) {
|
public final void writeChar(char value) {
|
||||||
writeInt(value);
|
writeInt(value);
|
||||||
@@ -312,9 +329,10 @@ public class JsonWriter extends Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void writeObjectB(Object obj) {
|
public final int writeObjectB(Object obj) {
|
||||||
super.writeObjectB(obj);
|
super.writeObjectB(obj);
|
||||||
writeTo('{');
|
writeTo('{');
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -328,8 +346,9 @@ public class JsonWriter extends Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void writeArrayB(int size) {
|
public final int writeArrayB(int size, Encodeable<Writer, Object> componentEncoder, Object obj) {
|
||||||
writeTo('[');
|
writeTo('[');
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -343,8 +362,9 @@ public class JsonWriter extends Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void writeMapB(int size) {
|
public final int writeMapB(int size, Encodeable<Writer, Object> keyEncoder, Encodeable<Writer, Object> valueEncoder, Object obj) {
|
||||||
writeTo('{');
|
writeTo('{');
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ package org.redkale.net;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.*;
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.*;
|
||||||
|
import java.util.function.*;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
import org.redkale.util.ObjectPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -21,7 +23,7 @@ import javax.net.ssl.SSLContext;
|
|||||||
*
|
*
|
||||||
* @author zhangjx
|
* @author zhangjx
|
||||||
*/
|
*/
|
||||||
public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCloseable {
|
public abstract class AsyncConnection implements ReadableByteChannel, WritableByteChannel, AutoCloseable {
|
||||||
|
|
||||||
protected SSLContext sslContext;
|
protected SSLContext sslContext;
|
||||||
|
|
||||||
@@ -33,12 +35,39 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
|
|||||||
|
|
||||||
protected volatile long writetime;
|
protected volatile long writetime;
|
||||||
|
|
||||||
//关闭数
|
protected final Supplier<ByteBuffer> bufferSupplier;
|
||||||
protected AtomicLong closedCounter;
|
|
||||||
|
protected final Consumer<ByteBuffer> bufferConsumer;
|
||||||
|
|
||||||
|
protected ByteBuffer readBuffer;
|
||||||
|
|
||||||
//在线数
|
//在线数
|
||||||
protected AtomicLong livingCounter;
|
protected AtomicLong livingCounter;
|
||||||
|
|
||||||
|
//关闭数
|
||||||
|
protected AtomicLong closedCounter;
|
||||||
|
|
||||||
|
protected Consumer<AsyncConnection> beforeCloseListener;
|
||||||
|
|
||||||
|
//关联的事件数, 小于1表示没有事件
|
||||||
|
protected final AtomicInteger eventing = new AtomicInteger();
|
||||||
|
|
||||||
|
protected AsyncConnection(Context context) {
|
||||||
|
this(context.getBufferSupplier(), context.getBufferConsumer(), context.getSSLContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AsyncConnection(ObjectPool<ByteBuffer> bufferPool, SSLContext sslContext) {
|
||||||
|
this(bufferPool, bufferPool, sslContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AsyncConnection(Supplier<ByteBuffer> bufferSupplier, Consumer<ByteBuffer> bufferConsumer, SSLContext sslContext) {
|
||||||
|
Objects.requireNonNull(bufferSupplier);
|
||||||
|
Objects.requireNonNull(bufferConsumer);
|
||||||
|
this.bufferSupplier = bufferSupplier;
|
||||||
|
this.bufferConsumer = bufferConsumer;
|
||||||
|
this.sslContext = sslContext;
|
||||||
|
}
|
||||||
|
|
||||||
public final long getLastReadTime() {
|
public final long getLastReadTime() {
|
||||||
return readtime;
|
return readtime;
|
||||||
}
|
}
|
||||||
@@ -47,19 +76,50 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
|
|||||||
return writetime;
|
return writetime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final int increEventing() {
|
||||||
|
return eventing.incrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int decreEventing() {
|
||||||
|
return eventing.decrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract boolean isOpen();
|
||||||
|
|
||||||
public abstract boolean isTCP();
|
public abstract boolean isTCP();
|
||||||
|
|
||||||
|
public abstract boolean shutdownInput();
|
||||||
|
|
||||||
|
public abstract boolean shutdownOutput();
|
||||||
|
|
||||||
|
public abstract <T> boolean setOption(SocketOption<T> name, T value);
|
||||||
|
|
||||||
|
public abstract Set<SocketOption<?>> supportedOptions();
|
||||||
|
|
||||||
public abstract SocketAddress getRemoteAddress();
|
public abstract SocketAddress getRemoteAddress();
|
||||||
|
|
||||||
public abstract SocketAddress getLocalAddress();
|
public abstract SocketAddress getLocalAddress();
|
||||||
|
|
||||||
public abstract int getReadTimeoutSecond();
|
public abstract int getReadTimeoutSeconds();
|
||||||
|
|
||||||
public abstract int getWriteTimeoutSecond();
|
public abstract int getWriteTimeoutSeconds();
|
||||||
|
|
||||||
public abstract void setReadTimeoutSecond(int readTimeoutSecond);
|
public abstract void setReadTimeoutSeconds(int readTimeoutSeconds);
|
||||||
|
|
||||||
public abstract void setWriteTimeoutSecond(int writeTimeoutSecond);
|
public abstract void setWriteTimeoutSeconds(int writeTimeoutSeconds);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract int read(ByteBuffer dst) throws IOException;
|
||||||
|
|
||||||
|
public abstract void read(CompletionHandler<Integer, ByteBuffer> handler);
|
||||||
|
|
||||||
|
public abstract void read(long timeout, TimeUnit unit, CompletionHandler<Integer, ByteBuffer> handler);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract int write(ByteBuffer src) throws IOException;
|
||||||
|
|
||||||
|
public abstract <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler);
|
||||||
|
|
||||||
public final <A> void write(ByteBuffer[] srcs, A attachment, CompletionHandler<Integer, ? super A> handler) {
|
public final <A> void write(ByteBuffer[] srcs, A attachment, CompletionHandler<Integer, ? super A> handler) {
|
||||||
write(srcs, 0, srcs.length, attachment, handler);
|
write(srcs, 0, srcs.length, attachment, handler);
|
||||||
@@ -67,6 +127,36 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
|
|||||||
|
|
||||||
public abstract <A> void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler<Integer, ? super A> handler);
|
public abstract <A> void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler<Integer, ? super A> handler);
|
||||||
|
|
||||||
|
public void setReadBuffer(Buffer buffer) {
|
||||||
|
if (this.readBuffer != null) throw new RuntimeException("repeat AsyncConnection.setReadBuffer");
|
||||||
|
this.readBuffer = (ByteBuffer) buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer pollReadBuffer() {
|
||||||
|
ByteBuffer rs = this.readBuffer;
|
||||||
|
if (rs != null) {
|
||||||
|
this.readBuffer = null;
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
return bufferSupplier.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offerBuffer(Buffer buffer) {
|
||||||
|
if (buffer == null) return;
|
||||||
|
bufferConsumer.accept((ByteBuffer) buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offerBuffer(Buffer... buffers) {
|
||||||
|
if (buffers == null) return;
|
||||||
|
for (Buffer buffer : buffers) {
|
||||||
|
bufferConsumer.accept((ByteBuffer) buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer pollWriteBuffer() {
|
||||||
|
return bufferSupplier.get();
|
||||||
|
}
|
||||||
|
|
||||||
public void dispose() {//同close, 只是去掉throws IOException
|
public void dispose() {//同close, 只是去掉throws IOException
|
||||||
try {
|
try {
|
||||||
this.close();
|
this.close();
|
||||||
@@ -74,6 +164,11 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AsyncConnection beforeCloseListener(Consumer<AsyncConnection> beforeCloseListener) {
|
||||||
|
this.beforeCloseListener = beforeCloseListener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if (closedCounter != null) {
|
if (closedCounter != null) {
|
||||||
@@ -84,6 +179,15 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
|
|||||||
livingCounter.decrementAndGet();
|
livingCounter.decrementAndGet();
|
||||||
livingCounter = null;
|
livingCounter = null;
|
||||||
}
|
}
|
||||||
|
if (beforeCloseListener != null) {
|
||||||
|
try {
|
||||||
|
beforeCloseListener.accept(this);
|
||||||
|
} catch (Exception io) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.readBuffer != null) {
|
||||||
|
bufferConsumer.accept(this.readBuffer);
|
||||||
|
}
|
||||||
if (attributes == null) return;
|
if (attributes == null) return;
|
||||||
try {
|
try {
|
||||||
for (Object obj : attributes.values()) {
|
for (Object obj : attributes.values()) {
|
||||||
@@ -128,61 +232,80 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
|
|||||||
/**
|
/**
|
||||||
* 创建TCP协议客户端连接
|
* 创建TCP协议客户端连接
|
||||||
*
|
*
|
||||||
* @param address 连接点子
|
* @param bufferPool ByteBuffer对象池
|
||||||
* @param group 连接AsynchronousChannelGroup
|
* @param address 连接点子
|
||||||
* @param readTimeoutSecond 读取超时秒数
|
* @param group 连接AsynchronousChannelGroup
|
||||||
* @param writeTimeoutSecond 写入超时秒数
|
* @param readTimeoutSeconds 读取超时秒数
|
||||||
|
* @param writeTimeoutSeconds 写入超时秒数
|
||||||
*
|
*
|
||||||
* @return 连接CompletableFuture
|
* @return 连接CompletableFuture
|
||||||
*/
|
*/
|
||||||
public static CompletableFuture<AsyncConnection> createTCP(final AsynchronousChannelGroup group, final SocketAddress address,
|
public static CompletableFuture<AsyncConnection> createTCP(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousChannelGroup group,
|
||||||
final int readTimeoutSecond, final int writeTimeoutSecond) {
|
final SocketAddress address, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
|
||||||
return createTCP(group, null, address, false, readTimeoutSecond, writeTimeoutSecond);
|
return createTCP(bufferPool, group, null, address, readTimeoutSeconds, writeTimeoutSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建TCP协议客户端连接
|
* 创建TCP协议客户端连接
|
||||||
*
|
*
|
||||||
* @param address 连接点子
|
* @param context Context
|
||||||
* @param sslContext SSLContext
|
* @param address 连接点子
|
||||||
* @param group 连接AsynchronousChannelGroup
|
* @param group 连接AsynchronousChannelGroup
|
||||||
* @param readTimeoutSecond 读取超时秒数
|
* @param readTimeoutSeconds 读取超时秒数
|
||||||
* @param writeTimeoutSecond 写入超时秒数
|
* @param writeTimeoutSeconds 写入超时秒数
|
||||||
*
|
*
|
||||||
* @return 连接CompletableFuture
|
* @return 连接CompletableFuture
|
||||||
*/
|
*/
|
||||||
public static CompletableFuture<AsyncConnection> createTCP(final AsynchronousChannelGroup group, final SSLContext sslContext,
|
public static CompletableFuture<AsyncConnection> createTCP(final Context context, final AsynchronousChannelGroup group,
|
||||||
final SocketAddress address, final int readTimeoutSecond, final int writeTimeoutSecond) {
|
final SocketAddress address, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
|
||||||
return createTCP(group, sslContext, address, false, readTimeoutSecond, writeTimeoutSecond);
|
return createTCP(context.getBufferSupplier(), context.getBufferConsumer(), group, context.getSSLContext(), address, readTimeoutSeconds, writeTimeoutSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建TCP协议客户端连接
|
* 创建TCP协议客户端连接
|
||||||
*
|
*
|
||||||
* @param address 连接点子
|
* @param bufferPool ByteBuffer对象池
|
||||||
* @param sslContext SSLContext
|
* @param address 连接点子
|
||||||
* @param group 连接AsynchronousChannelGroup
|
* @param sslContext SSLContext
|
||||||
* @param noDelay TcpNoDelay
|
* @param group 连接AsynchronousChannelGroup
|
||||||
* @param readTimeoutSecond 读取超时秒数
|
* @param readTimeoutSeconds 读取超时秒数
|
||||||
* @param writeTimeoutSecond 写入超时秒数
|
* @param writeTimeoutSeconds 写入超时秒数
|
||||||
*
|
*
|
||||||
* @return 连接CompletableFuture
|
* @return 连接CompletableFuture
|
||||||
*/
|
*/
|
||||||
public static CompletableFuture<AsyncConnection> createTCP(final AsynchronousChannelGroup group, final SSLContext sslContext,
|
public static CompletableFuture<AsyncConnection> createTCP(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousChannelGroup group, final SSLContext sslContext,
|
||||||
final SocketAddress address, final boolean noDelay, final int readTimeoutSecond, final int writeTimeoutSecond) {
|
final SocketAddress address, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
|
||||||
final CompletableFuture future = new CompletableFuture();
|
return createTCP(bufferPool, bufferPool, group, sslContext, address, readTimeoutSeconds, writeTimeoutSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建TCP协议客户端连接
|
||||||
|
*
|
||||||
|
* @param bufferSupplier ByteBuffer生产器
|
||||||
|
* @param bufferConsumer ByteBuffer回收器
|
||||||
|
* @param address 连接点子
|
||||||
|
* @param sslContext SSLContext
|
||||||
|
* @param group 连接AsynchronousChannelGroup
|
||||||
|
* @param readTimeoutSeconds 读取超时秒数
|
||||||
|
* @param writeTimeoutSeconds 写入超时秒数
|
||||||
|
*
|
||||||
|
* @return 连接CompletableFuture
|
||||||
|
*/
|
||||||
|
public static CompletableFuture<AsyncConnection> createTCP(final Supplier<ByteBuffer> bufferSupplier, Consumer<ByteBuffer> bufferConsumer, final AsynchronousChannelGroup group, final SSLContext sslContext,
|
||||||
|
final SocketAddress address, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
|
||||||
|
final CompletableFuture<AsyncConnection> future = new CompletableFuture<>();
|
||||||
try {
|
try {
|
||||||
final AsynchronousSocketChannel channel = AsynchronousSocketChannel.open(group);
|
final AsynchronousSocketChannel channel = AsynchronousSocketChannel.open(group);
|
||||||
|
try {
|
||||||
|
channel.setOption(StandardSocketOptions.TCP_NODELAY, true);
|
||||||
|
channel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
|
||||||
|
channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
channel.connect(address, null, new CompletionHandler<Void, Void>() {
|
channel.connect(address, null, new CompletionHandler<Void, Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void completed(Void result, Void attachment) {
|
public void completed(Void result, Void attachment) {
|
||||||
if (noDelay) {
|
future.complete(new TcpAioAsyncConnection(bufferSupplier, bufferConsumer, channel, sslContext, address, readTimeoutSeconds, writeTimeoutSeconds, null, null));
|
||||||
try {
|
|
||||||
channel.setOption(StandardSocketOptions.TCP_NODELAY, true);
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
future.complete(create(channel, sslContext, address, readTimeoutSecond, writeTimeoutSecond));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -196,443 +319,109 @@ public abstract class AsyncConnection implements AsynchronousByteChannel, AutoCl
|
|||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BIOUDPAsyncConnection extends AsyncConnection {
|
// public static AsyncConnection create(final Socket socket) {
|
||||||
|
// return create(socket, null, 0, 0);
|
||||||
private int readTimeoutSecond;
|
// }
|
||||||
|
// public static AsyncConnection create(final Socket socket, final SocketAddress addr0, final int readTimeoutSecond0, final int writeTimeoutSecond0) {
|
||||||
private int writeTimeoutSecond;
|
// return new TcpBioAsyncConnection(socket, addr0, readTimeoutSecond0, writeTimeoutSecond0, null, null);
|
||||||
|
// }
|
||||||
private final DatagramChannel channel;
|
//
|
||||||
|
// public static AsyncConnection create(final Socket socket, final SocketAddress addr0, final int readTimeoutSecond0,
|
||||||
private final SocketAddress remoteAddress;
|
// final int writeTimeoutSecond0, final AtomicLong livingCounter, final AtomicLong closedCounter) {
|
||||||
|
// return new TcpBioAsyncConnection(socket, addr0, readTimeoutSecond0, writeTimeoutSecond0, livingCounter, closedCounter);
|
||||||
private final boolean client;
|
// }
|
||||||
|
//
|
||||||
public BIOUDPAsyncConnection(final DatagramChannel ch, SocketAddress addr,
|
// public static AsyncConnection create(final SocketChannel ch, SocketAddress addr, final Selector selector,
|
||||||
final boolean client0, final int readTimeoutSecond0, final int writeTimeoutSecond0) {
|
// final int readTimeoutSeconds0, final int writeTimeoutSeconds0) {
|
||||||
this.channel = ch;
|
// return new TcpNioAsyncConnection(ch, addr, selector, readTimeoutSeconds0, writeTimeoutSeconds0, null, null);
|
||||||
this.client = client0;
|
// }
|
||||||
this.readTimeoutSecond = readTimeoutSecond0;
|
//
|
||||||
this.writeTimeoutSecond = writeTimeoutSecond0;
|
// public static AsyncConnection create(final SocketChannel ch, final SocketAddress addr0, final Selector selector, final Context context) {
|
||||||
this.remoteAddress = addr;
|
// return new TcpNioAsyncConnection(ch, addr0, selector, context.readTimeoutSeconds, context.writeTimeoutSeconds, null, null);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// public static AsyncConnection create(final SocketChannel ch, SocketAddress addr, final Selector selector,
|
||||||
public void setReadTimeoutSecond(int readTimeoutSecond) {
|
// final int readTimeoutSeconds0, final int writeTimeoutSeconds0,
|
||||||
this.readTimeoutSecond = readTimeoutSecond;
|
// final AtomicLong livingCounter, final AtomicLong closedCounter) {
|
||||||
}
|
// return new TcpNioAsyncConnection(ch, addr, selector, readTimeoutSeconds0, writeTimeoutSeconds0, livingCounter, closedCounter);
|
||||||
|
// }
|
||||||
@Override
|
public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final DatagramChannel ch,
|
||||||
public void setWriteTimeoutSecond(int writeTimeoutSecond) {
|
SocketAddress addr, final boolean client0,
|
||||||
this.writeTimeoutSecond = writeTimeoutSecond;
|
final int readTimeoutSeconds0, final int writeTimeoutSeconds0) {
|
||||||
}
|
return new UdpBioAsyncConnection(bufferPool, bufferPool, ch, null, addr, client0, readTimeoutSeconds0, writeTimeoutSeconds0, null, null);
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getReadTimeoutSecond() {
|
|
||||||
return this.readTimeoutSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getWriteTimeoutSecond() {
|
|
||||||
return this.writeTimeoutSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final SocketAddress getRemoteAddress() {
|
|
||||||
return remoteAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SocketAddress getLocalAddress() {
|
|
||||||
try {
|
|
||||||
return channel.getLocalAddress();
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <A> void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler<Integer, ? super A> handler) {
|
|
||||||
try {
|
|
||||||
int rs = 0;
|
|
||||||
for (int i = offset; i < offset + length; i++) {
|
|
||||||
rs += channel.send(srcs[i], remoteAddress);
|
|
||||||
if (i != offset) Thread.sleep(10);
|
|
||||||
}
|
|
||||||
this.writetime = System.currentTimeMillis();
|
|
||||||
if (handler != null) handler.completed(rs, attachment);
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (handler != null) handler.failed(e, attachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <A> void read(ByteBuffer dst, A attachment, CompletionHandler<Integer, ? super A> handler) {
|
|
||||||
try {
|
|
||||||
int rs = channel.read(dst);
|
|
||||||
this.readtime = System.currentTimeMillis();
|
|
||||||
if (handler != null) handler.completed(rs, attachment);
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (handler != null) handler.failed(e, attachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Future<Integer> read(ByteBuffer dst) {
|
|
||||||
try {
|
|
||||||
int rs = channel.read(dst);
|
|
||||||
this.readtime = System.currentTimeMillis();
|
|
||||||
return CompletableFuture.completedFuture(rs);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler) {
|
|
||||||
try {
|
|
||||||
int rs = channel.send(src, remoteAddress);
|
|
||||||
this.writetime = System.currentTimeMillis();
|
|
||||||
if (handler != null) handler.completed(rs, attachment);
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (handler != null) handler.failed(e, attachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Future<Integer> write(ByteBuffer src) {
|
|
||||||
try {
|
|
||||||
int rs = channel.send(src, remoteAddress);
|
|
||||||
this.writetime = System.currentTimeMillis();
|
|
||||||
return CompletableFuture.completedFuture(rs);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void close() throws IOException {
|
|
||||||
super.close();
|
|
||||||
if (client) channel.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean isOpen() {
|
|
||||||
return channel.isOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean isTCP() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsyncConnection create(final DatagramChannel ch, SocketAddress addr,
|
public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final DatagramChannel ch,
|
||||||
final boolean client0, final int readTimeoutSecond0, final int writeTimeoutSecond0) {
|
SocketAddress addr, final boolean client0,
|
||||||
return new BIOUDPAsyncConnection(ch, addr, client0, readTimeoutSecond0, writeTimeoutSecond0);
|
final int readTimeoutSeconds0, final int writeTimeoutSeconds0,
|
||||||
|
final AtomicLong livingCounter, final AtomicLong closedCounter) {
|
||||||
|
return new UdpBioAsyncConnection(bufferPool, bufferPool, ch, null, addr, client0, readTimeoutSeconds0, writeTimeoutSeconds0, livingCounter, closedCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BIOTCPAsyncConnection extends AsyncConnection {
|
public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final DatagramChannel ch, SSLContext sslContext,
|
||||||
|
SocketAddress addr, final boolean client0,
|
||||||
private int readTimeoutSecond;
|
final int readTimeoutSeconds0, final int writeTimeoutSeconds0) {
|
||||||
|
return new UdpBioAsyncConnection(bufferPool, bufferPool, ch, sslContext, addr, client0, readTimeoutSeconds0, writeTimeoutSeconds0, null, null);
|
||||||
private int writeTimeoutSecond;
|
|
||||||
|
|
||||||
private final Socket socket;
|
|
||||||
|
|
||||||
private final ReadableByteChannel readChannel;
|
|
||||||
|
|
||||||
private final WritableByteChannel writeChannel;
|
|
||||||
|
|
||||||
private final SocketAddress remoteAddress;
|
|
||||||
|
|
||||||
public BIOTCPAsyncConnection(final Socket socket, final SocketAddress addr0, final int readTimeoutSecond0, final int writeTimeoutSecond0) {
|
|
||||||
this.socket = socket;
|
|
||||||
ReadableByteChannel rc = null;
|
|
||||||
WritableByteChannel wc = null;
|
|
||||||
try {
|
|
||||||
socket.setSoTimeout(Math.max(readTimeoutSecond0, writeTimeoutSecond0));
|
|
||||||
rc = Channels.newChannel(socket.getInputStream());
|
|
||||||
wc = Channels.newChannel(socket.getOutputStream());
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
this.readChannel = rc;
|
|
||||||
this.writeChannel = wc;
|
|
||||||
this.readTimeoutSecond = readTimeoutSecond0;
|
|
||||||
this.writeTimeoutSecond = writeTimeoutSecond0;
|
|
||||||
SocketAddress addr = addr0;
|
|
||||||
if (addr == null) {
|
|
||||||
try {
|
|
||||||
addr = socket.getRemoteSocketAddress();
|
|
||||||
} catch (Exception e) {
|
|
||||||
//do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.remoteAddress = addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTCP() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SocketAddress getRemoteAddress() {
|
|
||||||
return remoteAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SocketAddress getLocalAddress() {
|
|
||||||
return socket.getLocalSocketAddress();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getReadTimeoutSecond() {
|
|
||||||
return readTimeoutSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getWriteTimeoutSecond() {
|
|
||||||
return writeTimeoutSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setReadTimeoutSecond(int readTimeoutSecond) {
|
|
||||||
this.readTimeoutSecond = readTimeoutSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setWriteTimeoutSecond(int writeTimeoutSecond) {
|
|
||||||
this.writeTimeoutSecond = writeTimeoutSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <A> void write(ByteBuffer[] srcs, int offset, int length, A attachment, CompletionHandler<Integer, ? super A> handler) {
|
|
||||||
try {
|
|
||||||
int rs = 0;
|
|
||||||
for (int i = offset; i < offset + length; i++) {
|
|
||||||
rs += writeChannel.write(srcs[i]);
|
|
||||||
}
|
|
||||||
this.writetime = System.currentTimeMillis();
|
|
||||||
if (handler != null) handler.completed(rs, attachment);
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (handler != null) handler.failed(e, attachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <A> void read(ByteBuffer dst, A attachment, CompletionHandler<Integer, ? super A> handler) {
|
|
||||||
try {
|
|
||||||
int rs = readChannel.read(dst);
|
|
||||||
this.readtime = System.currentTimeMillis();
|
|
||||||
if (handler != null) handler.completed(rs, attachment);
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (handler != null) handler.failed(e, attachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Future<Integer> read(ByteBuffer dst) {
|
|
||||||
try {
|
|
||||||
int rs = readChannel.read(dst);
|
|
||||||
this.readtime = System.currentTimeMillis();
|
|
||||||
return CompletableFuture.completedFuture(rs);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler) {
|
|
||||||
try {
|
|
||||||
int rs = writeChannel.write(src);
|
|
||||||
this.writetime = System.currentTimeMillis();
|
|
||||||
if (handler != null) handler.completed(rs, attachment);
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (handler != null) handler.failed(e, attachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Future<Integer> write(ByteBuffer src) {
|
|
||||||
try {
|
|
||||||
int rs = writeChannel.write(src);
|
|
||||||
this.writetime = System.currentTimeMillis();
|
|
||||||
return CompletableFuture.completedFuture(rs);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
super.close();
|
|
||||||
this.socket.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isOpen() {
|
|
||||||
return !socket.isClosed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final DatagramChannel ch, SSLContext sslContext,
|
||||||
* 通常用于 ssl socket
|
SocketAddress addr, final boolean client0,
|
||||||
*
|
final int readTimeoutSeconds0, final int writeTimeoutSeconds0,
|
||||||
* @param socket Socket对象
|
final AtomicLong livingCounter, final AtomicLong closedCounter) {
|
||||||
*
|
return new UdpBioAsyncConnection(bufferPool, bufferPool, ch, sslContext, addr, client0, readTimeoutSeconds0, writeTimeoutSeconds0, livingCounter, closedCounter);
|
||||||
* @return 连接对象
|
|
||||||
*/
|
|
||||||
public static AsyncConnection create(final Socket socket) {
|
|
||||||
return create(socket, null, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsyncConnection create(final Socket socket, final SocketAddress addr0, final int readTimeoutSecond0, final int writeTimeoutSecond0) {
|
public static AsyncConnection create(final Context context, final AsynchronousSocketChannel ch) {
|
||||||
return new BIOTCPAsyncConnection(socket, addr0, readTimeoutSecond0, writeTimeoutSecond0);
|
return create(context, ch, (SocketAddress) null, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AIOTCPAsyncConnection extends AsyncConnection {
|
public static AsyncConnection create(final Context context, final AsynchronousSocketChannel ch,
|
||||||
|
final SocketAddress addr0, final AtomicLong livingCounter, final AtomicLong closedCounter) {
|
||||||
private int readTimeoutSecond;
|
return new TcpAioAsyncConnection(context.getBufferSupplier(), context.getBufferConsumer(), ch, context.sslContext, addr0, context.readTimeoutSeconds, context.writeTimeoutSeconds, livingCounter, closedCounter);
|
||||||
|
|
||||||
private int writeTimeoutSecond;
|
|
||||||
|
|
||||||
private final AsynchronousSocketChannel channel;
|
|
||||||
|
|
||||||
private final SocketAddress remoteAddress;
|
|
||||||
|
|
||||||
public AIOTCPAsyncConnection(final AsynchronousSocketChannel ch, SSLContext sslContext,
|
|
||||||
final SocketAddress addr0, final int readTimeoutSecond0, final int writeTimeoutSecond0) {
|
|
||||||
this.channel = ch;
|
|
||||||
this.sslContext = sslContext;
|
|
||||||
this.readTimeoutSecond = readTimeoutSecond0;
|
|
||||||
this.writeTimeoutSecond = writeTimeoutSecond0;
|
|
||||||
SocketAddress addr = addr0;
|
|
||||||
if (addr == null) {
|
|
||||||
try {
|
|
||||||
addr = ch.getRemoteAddress();
|
|
||||||
} catch (Exception e) {
|
|
||||||
//do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.remoteAddress = addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <A> void read(ByteBuffer dst, A attachment, CompletionHandler<Integer, ? super A> handler) {
|
|
||||||
this.readtime = System.currentTimeMillis();
|
|
||||||
if (readTimeoutSecond > 0) {
|
|
||||||
channel.read(dst, readTimeoutSecond, TimeUnit.SECONDS, attachment, handler);
|
|
||||||
} else {
|
|
||||||
channel.read(dst, attachment, handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler) {
|
|
||||||
this.writetime = System.currentTimeMillis();
|
|
||||||
if (writeTimeoutSecond > 0) {
|
|
||||||
channel.write(src, writeTimeoutSecond, TimeUnit.SECONDS, attachment, handler);
|
|
||||||
} else {
|
|
||||||
channel.write(src, attachment, handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <A> void write(ByteBuffer[] srcs, int offset, int length, A attachment, final CompletionHandler<Integer, ? super A> handler) {
|
|
||||||
this.writetime = System.currentTimeMillis();
|
|
||||||
channel.write(srcs, offset, length, writeTimeoutSecond > 0 ? writeTimeoutSecond : 60, TimeUnit.SECONDS,
|
|
||||||
attachment, new CompletionHandler<Long, A>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void completed(Long result, A attachment) {
|
|
||||||
handler.completed(result.intValue(), attachment);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void failed(Throwable exc, A attachment) {
|
|
||||||
handler.failed(exc, attachment);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setReadTimeoutSecond(int readTimeoutSecond) {
|
|
||||||
this.readTimeoutSecond = readTimeoutSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setWriteTimeoutSecond(int writeTimeoutSecond) {
|
|
||||||
this.writeTimeoutSecond = writeTimeoutSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getReadTimeoutSecond() {
|
|
||||||
return this.readTimeoutSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getWriteTimeoutSecond() {
|
|
||||||
return this.writeTimeoutSecond;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final SocketAddress getRemoteAddress() {
|
|
||||||
return remoteAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SocketAddress getLocalAddress() {
|
|
||||||
try {
|
|
||||||
return channel.getLocalAddress();
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Future<Integer> read(ByteBuffer dst) {
|
|
||||||
return channel.read(dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Future<Integer> write(ByteBuffer src) {
|
|
||||||
return channel.write(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void close() throws IOException {
|
|
||||||
super.close();
|
|
||||||
channel.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean isOpen() {
|
|
||||||
return channel.isOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean isTCP() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsyncConnection create(final AsynchronousSocketChannel ch) {
|
public static AsyncConnection create(final Context context, final AsynchronousSocketChannel ch,
|
||||||
return create(ch, null, 0, 0);
|
final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
|
||||||
|
return new TcpAioAsyncConnection(context.getBufferSupplier(), context.getBufferConsumer(), ch, null, addr0, readTimeoutSeconds, writeTimeoutSeconds, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsyncConnection create(final AsynchronousSocketChannel ch, final SocketAddress addr0, final int readTimeoutSecond, final int writeTimeoutSecond) {
|
public static AsyncConnection create(final Context context, final AsynchronousSocketChannel ch, SSLContext sslContext,
|
||||||
return new AIOTCPAsyncConnection(ch, null, addr0, readTimeoutSecond, writeTimeoutSecond);
|
final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
|
||||||
|
return new TcpAioAsyncConnection(context.getBufferSupplier(), context.getBufferConsumer(), ch, sslContext, addr0, readTimeoutSeconds, writeTimeoutSeconds, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsyncConnection create(final AsynchronousSocketChannel ch, SSLContext sslContext, final SocketAddress addr0, final int readTimeoutSecond, final int writeTimeoutSecond) {
|
public static AsyncConnection create(final Context context, final AsynchronousSocketChannel ch,
|
||||||
return new AIOTCPAsyncConnection(ch, sslContext, addr0, readTimeoutSecond, writeTimeoutSecond);
|
final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds, final AtomicLong livingCounter, final AtomicLong closedCounter) {
|
||||||
|
return new TcpAioAsyncConnection(context.getBufferSupplier(), context.getBufferConsumer(), ch, null, addr0, readTimeoutSeconds, writeTimeoutSeconds, livingCounter, closedCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsyncConnection create(final AsynchronousSocketChannel ch, final SocketAddress addr0, final Context context) {
|
public static AsyncConnection create(final Context context, final AsynchronousSocketChannel ch, SSLContext sslContext,
|
||||||
return new AIOTCPAsyncConnection(ch, context.sslContext, addr0, context.readTimeoutSecond, context.writeTimeoutSecond);
|
final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds, final AtomicLong livingCounter, final AtomicLong closedCounter) {
|
||||||
|
return new TcpAioAsyncConnection(context.getBufferSupplier(), context.getBufferConsumer(), ch, sslContext, addr0, readTimeoutSeconds, writeTimeoutSeconds, livingCounter, closedCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousSocketChannel ch) {
|
||||||
|
return create(bufferPool, ch, null, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousSocketChannel ch,
|
||||||
|
final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
|
||||||
|
return new TcpAioAsyncConnection(bufferPool, bufferPool, ch, null, addr0, readTimeoutSeconds, writeTimeoutSeconds, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousSocketChannel ch, SSLContext sslContext,
|
||||||
|
final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
|
||||||
|
return new TcpAioAsyncConnection(bufferPool, bufferPool, ch, sslContext, addr0, readTimeoutSeconds, writeTimeoutSeconds, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousSocketChannel ch,
|
||||||
|
final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds, final AtomicLong livingCounter, final AtomicLong closedCounter) {
|
||||||
|
return new TcpAioAsyncConnection(bufferPool, bufferPool, ch, null, addr0, readTimeoutSeconds, writeTimeoutSeconds, livingCounter, closedCounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AsyncConnection create(final ObjectPool<ByteBuffer> bufferPool, final AsynchronousSocketChannel ch, SSLContext sslContext,
|
||||||
|
final SocketAddress addr0, final int readTimeoutSeconds, final int writeTimeoutSeconds, final AtomicLong livingCounter, final AtomicLong closedCounter) {
|
||||||
|
return new TcpAioAsyncConnection(bufferPool, bufferPool, ch, sslContext, addr0, readTimeoutSeconds, writeTimeoutSeconds, livingCounter, closedCounter);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.net;
|
package org.redkale.net;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
import java.nio.channels.AsynchronousChannelGroup;
|
|
||||||
import java.nio.charset.*;
|
import java.nio.charset.*;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.function.*;
|
import java.util.function.*;
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
@@ -28,8 +27,6 @@ import org.redkale.util.*;
|
|||||||
*/
|
*/
|
||||||
public class Context {
|
public class Context {
|
||||||
|
|
||||||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
|
||||||
|
|
||||||
//服务启动时间
|
//服务启动时间
|
||||||
protected final long serverStartTime;
|
protected final long serverStartTime;
|
||||||
|
|
||||||
@@ -51,21 +48,6 @@ public class Context {
|
|||||||
//服务的根Servlet
|
//服务的根Servlet
|
||||||
protected final PrepareServlet prepare;
|
protected final PrepareServlet prepare;
|
||||||
|
|
||||||
//服务的监听地址
|
|
||||||
private final InetSocketAddress address;
|
|
||||||
|
|
||||||
//字符集
|
|
||||||
protected final Charset charset;
|
|
||||||
|
|
||||||
//请求内容的大小上限, 默认64K
|
|
||||||
protected final int maxbody;
|
|
||||||
|
|
||||||
//IO读取的超时时间
|
|
||||||
protected final int readTimeoutSecond;
|
|
||||||
|
|
||||||
//IO写入的超时时间
|
|
||||||
protected final int writeTimeoutSecond;
|
|
||||||
|
|
||||||
//日志Logger
|
//日志Logger
|
||||||
protected final Logger logger;
|
protected final Logger logger;
|
||||||
|
|
||||||
@@ -78,10 +60,38 @@ public class Context {
|
|||||||
//依赖注入工厂类
|
//依赖注入工厂类
|
||||||
protected final ResourceFactory resourceFactory;
|
protected final ResourceFactory resourceFactory;
|
||||||
|
|
||||||
|
//最大连接数, 为0表示没限制
|
||||||
|
protected int maxconns;
|
||||||
|
|
||||||
|
//请求内容的大小上限, 默认64K
|
||||||
|
protected int maxbody;
|
||||||
|
|
||||||
|
//keep alive IO读取的超时时间
|
||||||
|
protected int aliveTimeoutSeconds;
|
||||||
|
|
||||||
|
//IO读取的超时时间
|
||||||
|
protected int readTimeoutSeconds;
|
||||||
|
|
||||||
|
//IO写入的超时时间
|
||||||
|
protected int writeTimeoutSeconds;
|
||||||
|
|
||||||
|
//服务的监听地址
|
||||||
|
protected InetSocketAddress address;
|
||||||
|
|
||||||
|
//字符集
|
||||||
|
protected Charset charset;
|
||||||
|
|
||||||
|
public Context(ContextConfig config) {
|
||||||
|
this(config.serverStartTime, config.logger, config.executor, config.sslContext,
|
||||||
|
config.bufferCapacity, config.bufferPool, config.responsePool, config.maxconns, config.maxbody,
|
||||||
|
config.charset, config.address, config.resourceFactory, config.prepare,
|
||||||
|
config.aliveTimeoutSeconds, config.readTimeoutSeconds, config.writeTimeoutSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
public Context(long serverStartTime, Logger logger, ThreadPoolExecutor executor, SSLContext sslContext,
|
public Context(long serverStartTime, Logger logger, ThreadPoolExecutor executor, SSLContext sslContext,
|
||||||
int bufferCapacity, ObjectPool<ByteBuffer> bufferPool, ObjectPool<Response> responsePool,
|
int bufferCapacity, ObjectPool<ByteBuffer> bufferPool, ObjectPool<Response> responsePool, final int maxconns,
|
||||||
final int maxbody, Charset charset, InetSocketAddress address, ResourceFactory resourceFactory,
|
final int maxbody, Charset charset, InetSocketAddress address, ResourceFactory resourceFactory,
|
||||||
final PrepareServlet prepare, final int readTimeoutSecond, final int writeTimeoutSecond) {
|
final PrepareServlet prepare, final int aliveTimeoutSeconds, final int readTimeoutSeconds, final int writeTimeoutSeconds) {
|
||||||
this.serverStartTime = serverStartTime;
|
this.serverStartTime = serverStartTime;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
@@ -89,13 +99,15 @@ public class Context {
|
|||||||
this.bufferCapacity = bufferCapacity;
|
this.bufferCapacity = bufferCapacity;
|
||||||
this.bufferPool = bufferPool;
|
this.bufferPool = bufferPool;
|
||||||
this.responsePool = responsePool;
|
this.responsePool = responsePool;
|
||||||
|
this.maxconns = maxconns;
|
||||||
this.maxbody = maxbody;
|
this.maxbody = maxbody;
|
||||||
this.charset = UTF8.equals(charset) ? null : charset;
|
this.charset = StandardCharsets.UTF_8.equals(charset) ? null : charset;
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.prepare = prepare;
|
this.prepare = prepare;
|
||||||
this.resourceFactory = resourceFactory;
|
this.resourceFactory = resourceFactory;
|
||||||
this.readTimeoutSecond = readTimeoutSecond;
|
this.aliveTimeoutSeconds = aliveTimeoutSeconds;
|
||||||
this.writeTimeoutSecond = writeTimeoutSecond;
|
this.readTimeoutSeconds = readTimeoutSeconds;
|
||||||
|
this.writeTimeoutSeconds = writeTimeoutSeconds;
|
||||||
this.jsonFactory = JsonFactory.root();
|
this.jsonFactory = JsonFactory.root();
|
||||||
this.bsonFactory = BsonFactory.root();
|
this.bsonFactory = BsonFactory.root();
|
||||||
}
|
}
|
||||||
@@ -108,6 +120,10 @@ public class Context {
|
|||||||
return sslContext;
|
return sslContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMaxconns() {
|
||||||
|
return maxconns;
|
||||||
|
}
|
||||||
|
|
||||||
public int getMaxbody() {
|
public int getMaxbody() {
|
||||||
return maxbody;
|
return maxbody;
|
||||||
}
|
}
|
||||||
@@ -128,10 +144,6 @@ public class Context {
|
|||||||
return executor.submit(r);
|
return executor.submit(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsynchronousChannelGroup createAsynchronousChannelGroup() throws IOException {
|
|
||||||
return AsynchronousChannelGroup.withThreadPool(executor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void runAsync(Runnable r) {
|
public void runAsync(Runnable r) {
|
||||||
executor.execute(r);
|
executor.execute(r);
|
||||||
}
|
}
|
||||||
@@ -144,6 +156,10 @@ public class Context {
|
|||||||
return bufferPool;
|
return bufferPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Consumer<ByteBuffer> getBufferConsumer() {
|
||||||
|
return bufferPool;
|
||||||
|
}
|
||||||
|
|
||||||
public ByteBuffer pollBuffer() {
|
public ByteBuffer pollBuffer() {
|
||||||
return bufferPool.get();
|
return bufferPool.get();
|
||||||
}
|
}
|
||||||
@@ -159,16 +175,27 @@ public class Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void offerBuffer(Collection<ByteBuffer> buffers) {
|
||||||
|
if (buffers == null) return;
|
||||||
|
for (ByteBuffer buffer : buffers) {
|
||||||
|
bufferPool.accept(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Logger getLogger() {
|
public Logger getLogger() {
|
||||||
return logger;
|
return logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getReadTimeoutSecond() {
|
public int getAliveTimeoutSeconds() {
|
||||||
return readTimeoutSecond;
|
return aliveTimeoutSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWriteTimeoutSecond() {
|
public int getReadTimeoutSeconds() {
|
||||||
return writeTimeoutSecond;
|
return readTimeoutSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWriteTimeoutSeconds() {
|
||||||
|
return writeTimeoutSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonConvert getJsonConvert() {
|
public JsonConvert getJsonConvert() {
|
||||||
@@ -178,4 +205,60 @@ public class Context {
|
|||||||
public BsonConvert getBsonConvert() {
|
public BsonConvert getBsonConvert() {
|
||||||
return bsonFactory.getConvert();
|
return bsonFactory.getConvert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ContextConfig {
|
||||||
|
|
||||||
|
//服务启动时间
|
||||||
|
public long serverStartTime;
|
||||||
|
|
||||||
|
//Server的线程池
|
||||||
|
public ThreadPoolExecutor executor;
|
||||||
|
|
||||||
|
//SSL
|
||||||
|
public SSLContext sslContext;
|
||||||
|
|
||||||
|
//ByteBuffer的容量,默认8K
|
||||||
|
public int bufferCapacity;
|
||||||
|
|
||||||
|
//ByteBuffer对象池
|
||||||
|
public ObjectPool<ByteBuffer> bufferPool;
|
||||||
|
|
||||||
|
//Response对象池
|
||||||
|
public ObjectPool<Response> responsePool;
|
||||||
|
|
||||||
|
//服务的根Servlet
|
||||||
|
public PrepareServlet prepare;
|
||||||
|
|
||||||
|
//服务的监听地址
|
||||||
|
public InetSocketAddress address;
|
||||||
|
|
||||||
|
//字符集
|
||||||
|
public Charset charset;
|
||||||
|
|
||||||
|
//请求内容的大小上限, 默认64K
|
||||||
|
public int maxbody;
|
||||||
|
|
||||||
|
//最大连接数, 为0表示没限制
|
||||||
|
public int maxconns;
|
||||||
|
|
||||||
|
//keep alive IO读取的超时时间
|
||||||
|
public int aliveTimeoutSeconds;
|
||||||
|
|
||||||
|
//IO读取的超时时间
|
||||||
|
public int readTimeoutSeconds;
|
||||||
|
|
||||||
|
//IO写入的超时时间
|
||||||
|
public int writeTimeoutSeconds;
|
||||||
|
|
||||||
|
//日志Logger
|
||||||
|
public Logger logger;
|
||||||
|
|
||||||
|
//依赖注入工厂类
|
||||||
|
public ResourceFactory resourceFactory;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JsonConvert.root().convertTo(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
42
src/org/redkale/net/Cryptor.java
Normal file
42
src/org/redkale/net/Cryptor.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.redkale.net;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.function.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密解密接口
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
public interface Cryptor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
*
|
||||||
|
* @param buffers 待加密数据
|
||||||
|
* @param supplier ByteBuffer生成器
|
||||||
|
* @param consumer ByteBuffer回收器
|
||||||
|
*
|
||||||
|
* @return 加密后数据
|
||||||
|
*/
|
||||||
|
public ByteBuffer[] encrypt(ByteBuffer[] buffers, final Supplier<ByteBuffer> supplier, final Consumer<ByteBuffer> consumer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密
|
||||||
|
*
|
||||||
|
* @param buffers 待解密数据
|
||||||
|
* @param supplier ByteBuffer生成器
|
||||||
|
* @param consumer ByteBuffer回收器
|
||||||
|
*
|
||||||
|
* @return 解密后数据
|
||||||
|
*/
|
||||||
|
public ByteBuffer[] decrypt(ByteBuffer[] buffers, final Supplier<ByteBuffer> supplier, final Consumer<ByteBuffer> consumer);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user