6041 lines
240 KiB
Java
6041 lines
240 KiB
Java
/*
|
||
* To change this template, choose Tools | Templates
|
||
* and open the template in the editor.
|
||
*/
|
||
package org.redkale.util;
|
||
|
||
import java.io.*;
|
||
import java.lang.invoke.*;
|
||
import java.lang.reflect.*;
|
||
import java.math.*;
|
||
import java.net.*;
|
||
import java.net.http.HttpClient;
|
||
import java.nio.*;
|
||
import java.nio.channels.CompletionHandler;
|
||
import java.nio.charset.*;
|
||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||
import java.security.*;
|
||
import java.time.*;
|
||
import java.util.*;
|
||
import java.util.concurrent.*;
|
||
import java.util.concurrent.atomic.AtomicInteger;
|
||
import java.util.concurrent.locks.ReentrantLock;
|
||
import java.util.function.*;
|
||
import java.util.stream.Stream;
|
||
import java.util.zip.GZIPInputStream;
|
||
import javax.crypto.*;
|
||
import javax.crypto.spec.SecretKeySpec;
|
||
import org.redkale.annotation.ClassDepends;
|
||
import org.redkale.annotation.Priority;
|
||
import org.redkale.convert.json.JsonConvert;
|
||
|
||
/**
|
||
* 常见操作的工具类
|
||
*
|
||
* <p>详情见: https://redkale.org
|
||
*
|
||
* @author zhangjx
|
||
*/
|
||
public final class Utility {
|
||
|
||
private static final char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||
|
||
private static final int CPUS =
|
||
Integer.getInteger("redkale.cpus", Runtime.getRuntime().availableProcessors());
|
||
|
||
private static final int MAX_POW2 = 1 << 30;
|
||
|
||
private static final ConcurrentHashMap<Class, String> lambdaFieldNameCache = new ConcurrentHashMap();
|
||
|
||
private static final ConcurrentHashMap<Class, Class> lambdaClassNameCache = new ConcurrentHashMap();
|
||
|
||
private static final Class JAVA_RECORD_CLASS;
|
||
|
||
private static final SecureRandom random = new SecureRandom();
|
||
|
||
private static final IntFunction<CompletableFuture[]> futureArrayFunc = c -> new CompletableFuture[c];
|
||
|
||
private static final IntFunction<Serializable[]> serialArrayFunc = v -> new Serializable[v];
|
||
|
||
static {
|
||
Class clz = null;
|
||
try {
|
||
clz = Thread.currentThread().getContextClassLoader().loadClass("java.lang.Record");
|
||
} catch (Throwable t) { // JDK14以下版本会异常
|
||
}
|
||
JAVA_RECORD_CLASS = clz;
|
||
}
|
||
|
||
private static final Executor defaultExecutorConsumer = new Executor() {
|
||
@Override
|
||
public void execute(Runnable command) {
|
||
command.run();
|
||
}
|
||
};
|
||
|
||
// org.redkale.util.AnonymousThreadLocal
|
||
private static final String functionThreadLocalBinary =
|
||
"cafebabe0000004100480a000200030700040c000500060100156a6176612f6c616e672f5468726561644c6f63616c0100063c696e69743e010003282956090008000907000a0c000b000c0100256f72672f7265646b616c652f7574696c2f416e6f6e796d6f75735468726561644c6f63616c010008737570706c69657201001d4c6a6176612f7574696c2f66756e6374696f6e2f537570706c6965723b0a0008000e0c0005000f010020284c6a6176612f7574696c2f66756e6374696f6e2f537570706c6965723b29560b001100120700130c0014001501001b6a6176612f7574696c2f66756e6374696f6e2f537570706c69657201000367657401001428294c6a6176612f6c616e672f4f626a6563743b0a001700180700190c001a001b0100106a6176612f6c616e672f54687265616401000d63757272656e7454687265616401001428294c6a6176612f6c616e672f5468726561643b0a0017001d0c001e001f01000969735669727475616c01000328295a0a000200210c00220023010003736574010015284c6a6176612f6c616e672f4f626a6563743b29560a000800250c0026001501000c696e697469616c56616c75650a000200120a000800290c002a002b0100056170706c79010036284c6a6176612f7574696c2f66756e6374696f6e2f537570706c6965723b294c6a6176612f6c616e672f5468726561644c6f63616c3b07002d01001b6a6176612f7574696c2f66756e6374696f6e2f46756e6374696f6e0100095369676e61747572650100224c6a6176612f7574696c2f66756e6374696f6e2f537570706c6965723c54543b3e3b010004436f646501000f4c696e654e756d6265725461626c650100124c6f63616c5661726961626c655461626c65010004746869730100274c6f72672f7265646b616c652f7574696c2f416e6f6e796d6f75735468726561644c6f63616c3b0100164c6f63616c5661726961626c65547970655461626c6501002c4c6f72672f7265646b616c652f7574696c2f416e6f6e796d6f75735468726561644c6f63616c3c54543b3e3b0100104d6574686f64506172616d6574657273010025284c6a6176612f7574696c2f66756e6374696f6e2f537570706c6965723c54543b3e3b2956010040284c6a6176612f7574696c2f66756e6374696f6e2f537570706c6965723c54543b3e3b294c6a6176612f6c616e672f5468726561644c6f63616c3c54543b3e3b010005282954543b01000576616c75650100124c6a6176612f6c616e672f4f626a6563743b010001740100124c6a6176612f6c616e672f5468726561643b01000354543b01000d537461636b4d61705461626c650100062854543b29560700430100106a6176612f6c616e672f4f626a656374010026284c6a6176612f6c616e672f4f626a6563743b294c6a6176612f6c616e672f4f626a6563743b01008f3c543a4c6a6176612f6c616e672f4f626a6563743b3e4c6a6176612f6c616e672f5468726561644c6f63616c3c54543b3e3b4c6a6176612f7574696c2f66756e6374696f6e2f46756e6374696f6e3c4c6a6176612f7574696c2f66756e6374696f6e2f537570706c6965723c54543b3e3b4c6a6176612f6c616e672f5468726561644c6f63616c3c54543b3e3b3e3b01000a536f7572636546696c65010019416e6f6e796d6f75735468726561644c6f63616c2e6a6176610021000800020001002c00010012000b000c0001002e00000002002f000600010005000f0003003000000062000200020000000a2ab700012a2bb50007b10000000300310000000e000300000016000400170009001800320000001600020000000a0033003400000000000a000b000c000100350000001600020000000a0033003600000000000a000b002f000100370000000501000b0000002e0000000200380001002a002b00030030000000590003000200000009bb0008592bb7000db00000000300310000000600010000001b00320000001600020000000900330034000000000009000b000c000100350000001600020000000900330036000000000009000b002f000100370000000501000b0000002e0000000200390004002600150002003000000046000100010000000a2ab40007b900100100b00000000300310000000600010000002000320000000c00010000000a00330034000000350000000c00010000000a003300360000002e00000002003a00010022002300030030000000850002000300000011b800164d2cb6001c9a00082a2bb70020b10000000400310000001200040000002500040026000b00270010002900320000002000030000001100330034000000000011003b003c00010004000d003d003e000200350000001600020000001100330036000000000011003b003f00010040000000080001fc001007001700370000000501003b0000002e00000002004100010014001500020030000000730001000200000017b800164c2bb6001c99000a2ab60024a700072ab70027b00000000400310000000a00020000002d0004002e00320000001600020000001700330034000000040013003d003e000100350000000c00010000001700330036000000400000000c0002fc001207001743070042002e00000002003a1041002a0044000200300000004500020002000000092a2bc00011b60028b00000000300310000000600010000001200320000000c00010000000900330034000000350000000c00010000000900330036000000370000000501000b10000002002e0000000200450046000000020047";
|
||
|
||
private static final Function<Supplier, ThreadLocal> virtualThreadLocalFunction;
|
||
|
||
// org.redkale.util.AnonymousThreadFactory
|
||
private static final String functionThreadFactoryBinary =
|
||
"cafebabe0000004100450a000200030700040c000500060100106a6176612f6c616e672f4f626a6563740100063c696e69743e0100032829560a0008000907000a0c000b000c0100106a6176612f6c616e672f5468726561640100096f665669727475616c01002628294c6a6176612f6c616e672f546872656164244275696c646572244f665669727475616c3b0b000e000f0700100c001100120100226a6176612f6c616e672f546872656164244275696c646572244f665669727475616c010007666163746f727901002628294c6a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72793b09001400150700160c001100170100276f72672f7265646b616c652f7574696c2f416e6f6e796d6f7573546872656164466163746f72790100244c6a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72793b09001400190c001a001b0100046e616d650100124c6a6176612f6c616e672f537472696e673b0a0014001d0c0005001e010015284c6a6176612f6c616e672f537472696e673b29560b002000210700220c002300240100226a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72790100096e6577546872656164010028284c6a6176612f6c616e672f52756e6e61626c653b294c6a6176612f6c616e672f5468726561643b0a000800260c0027001e0100077365744e616d650700290100106a6176612f6c616e672f537472696e670a0014002b0c002c002d0100056170706c79010038284c6a6176612f6c616e672f537472696e673b294c6a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72793b07002f01001b6a6176612f7574696c2f66756e6374696f6e2f46756e6374696f6e010004436f646501000f4c696e654e756d6265725461626c650100124c6f63616c5661726961626c655461626c65010004746869730100294c6f72672f7265646b616c652f7574696c2f416e6f6e796d6f7573546872656164466163746f72793b0100104d6574686f64506172616d6574657273010001720100144c6a6176612f6c616e672f52756e6e61626c653b010001740100124c6a6176612f6c616e672f5468726561643b01000d537461636b4d61705461626c65010026284c6a6176612f6c616e672f4f626a6563743b294c6a6176612f6c616e672f4f626a6563743b0100095369676e617475726501008b4c6a6176612f6c616e672f4f626a6563743b4c6a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72793b4c6a6176612f7574696c2f66756e6374696f6e2f46756e6374696f6e3c4c6a6176612f6c616e672f537472696e673b4c6a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72793b3e3b01000a536f7572636546696c6501001b416e6f6e796d6f7573546872656164466163746f72792e6a61766101000c496e6e6572436c61737365730700420100186a6176612f6c616e672f546872656164244275696c6465720100074275696c6465720100094f665669727475616c00210014000200020020002e000200120011001700000012001a001b0000000400010005001e000200300000005600020002000000162ab700012ab80007b9000d0100b500132a2bb50018b10000000200310000001200040000001500040011001000160015001700320000001600020000001600330034000000000016001a001b000100350000000501001a00000001002c002d000200300000003d0003000200000009bb0014592bb7001cb00000000200310000000600010000001b00320000001600020000000900330034000000000009001a001b000100350000000501001a00000001002300240002003000000074000200030000001c2ab400132bb9001f02004d2ab40018c6000b2c2ab40018b600252cb000000003003100000012000400000020000b002100120022001a002400320000002000030000001c0033003400000000001c003600370001000b0011003800390002003a000000080001fc001a07000800350000000501003600001041002c003b000200300000003300020002000000092a2bc00028b6002ab00000000200310000000600010000000f00320000000c00010000000900330034000000350000000501001a10000003003c00000002003d003e00000002003f00400000001200020041000800430609000e004100440609";
|
||
|
||
private static final Function<String, ThreadFactory> virtualThreadFactoryFunction;
|
||
|
||
// org.redkale.util.AnonymousVirtualPoolFunction
|
||
private static final String functionVirtualPoolBinary =
|
||
"cafebabe0000004100610a000200030700040c000500060100106a6176612f6c616e672f4f626a6563740100063c696e69743e0100032829560a0008000907000a0c000b000c0100106a6176612f6c616e672f5468726561640100096f665669727475616c01002628294c6a6176612f6c616e672f546872656164244275696c646572244f665669727475616c3b0b000e000f0700100c001100120100226a6176612f6c616e672f546872656164244275696c646572244f665669727475616c010007666163746f727901002628294c6a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72793b0800140100075669727475616c0a001600170700180c0019001a0100106a6176612f6c616e672f537472696e67010006666f726d6174010039284c6a6176612f6c616e672f537472696e673b5b4c6a6176612f6c616e672f4f626a6563743b294c6a6176612f6c616e672f537472696e673b120000001c0c001d001e0100096e657754687265616401005c284c6a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72793b4c6a6176612f6c616e672f537472696e673b294c6a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72793b0a002000210700220c0023002401001e6a6176612f7574696c2f636f6e63757272656e742f4578656375746f72730100186e65775468726561645065725461736b4578656375746f7201004c284c6a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72793b294c6a6176612f7574696c2f636f6e63757272656e742f4578656375746f72536572766963653b0a002600270700280c0029002a01002d6f72672f7265646b616c652f7574696c2f416e6f6e796d6f75735669727475616c506f6f6c46756e6374696f6e0100056170706c7901003a284c6a6176612f6c616e672f537472696e673b294c6a6176612f7574696c2f636f6e63757272656e742f4578656375746f72536572766963653b0b002c002d07002e0c001d002f0100226a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f7279010028284c6a6176612f6c616e672f52756e6e61626c653b294c6a6176612f6c616e672f5468726561643b0a000800310c003200330100077365744e616d65010015284c6a6176612f6c616e672f537472696e673b295607003501001b6a6176612f7574696c2f66756e6374696f6e2f46756e6374696f6e010004436f646501000f4c696e654e756d6265725461626c650100124c6f63616c5661726961626c655461626c650100047468697301002f4c6f72672f7265646b616c652f7574696c2f416e6f6e796d6f75735669727475616c506f6f6c46756e6374696f6e3b0100107468726561644e616d65466f726d61740100124c6a6176612f6c616e672f537472696e673b0100244c6a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72793b01000a7468726561644e616d650100104d6574686f64506172616d6574657273010026284c6a6176612f6c616e672f4f626a6563743b294c6a6176612f6c616e672f4f626a6563743b01000e6c616d626461246170706c79243001005e284c6a6176612f7574696c2f636f6e63757272656e742f546872656164466163746f72793b4c6a6176612f6c616e672f537472696e673b4c6a6176612f6c616e672f52756e6e61626c653b294c6a6176612f6c616e672f5468726561643b010001720100144c6a6176612f6c616e672f52756e6e61626c653b010001740100124c6a6176612f6c616e672f5468726561643b0100095369676e61747572650100694c6a6176612f6c616e672f4f626a6563743b4c6a6176612f7574696c2f66756e6374696f6e2f46756e6374696f6e3c4c6a6176612f6c616e672f537472696e673b4c6a6176612f7574696c2f636f6e63757272656e742f4578656375746f72536572766963653b3e3b01000a536f7572636546696c65010021416e6f6e796d6f75735669727475616c506f6f6c46756e6374696f6e2e6a617661010010426f6f7473747261704d6574686f647310002f0f06004e0a0026004f0c004100420f0600510a005200530700540c005500560100226a6176612f6c616e672f696e766f6b652f4c616d6264614d657461666163746f727901000b6d657461666163746f72790100cc284c6a6176612f6c616e672f696e766f6b652f4d6574686f6448616e646c6573244c6f6f6b75703b4c6a6176612f6c616e672f537472696e673b4c6a6176612f6c616e672f696e766f6b652f4d6574686f64547970653b4c6a6176612f6c616e672f696e766f6b652f4d6574686f64547970653b4c6a6176612f6c616e672f696e766f6b652f4d6574686f6448616e646c653b4c6a6176612f6c616e672f696e766f6b652f4d6574686f64547970653b294c6a6176612f6c616e672f696e766f6b652f43616c6c536974653b01000c496e6e6572436c61737365730700590100186a6176612f6c616e672f546872656164244275696c6465720100074275696c6465720100094f665669727475616c07005d0100256a6176612f6c616e672f696e766f6b652f4d6574686f6448616e646c6573244c6f6f6b757007005f01001e6a6176612f6c616e672f696e766f6b652f4d6574686f6448616e646c65730100064c6f6f6b75700021002600020001003400000004000100050006000100360000002f00010001000000052ab70001b10000000200370000000600010000000f00380000000c0001000000050039003a000000010029002a00020036000000720005000400000022b80007b9000d01004d2b04bd00025903121353b800154e2c2dba001b0000b8001fb00000000200370000000e000300000013000900140017001500380000002a0004000000220039003a000000000022003b003c0001000900190011003d00020017000b003e003c0003003f0000000501003b0000104100290040000200360000003300020002000000092a2bc00016b60025b00000000200370000000600010000000f00380000000c0001000000090039003a0000003f0000000501003b1000100a00410042000100360000005f000200040000000f2a2cb9002b02004e2d2bb600302db00000000200370000000e00030000001600080017000d001800380000002a00040000000f0011003d00000000000f003e003c00010000000f0043004400020008000700450046000300040047000000020048004900000002004a004b0000000c000100500003004c004d004c00570000001a000300580008005a0609000e0058005b0609005c005e00600019";
|
||
|
||
private static final Function<String, ExecutorService> virtualPoolFunction;
|
||
|
||
// org.redkale.util.AnonymousVirtualExecutor
|
||
private static final String consumerVirtualExecutorBinary =
|
||
"cafebabe00000041002e0a000200030700040c000500060100106a6176612f6c616e672f4f626a6563740100063c696e69743e0100032829560a0008000907000a0c000b000c0100106a6176612f6c616e672f5468726561640100096f665669727475616c01002628294c6a6176612f6c616e672f546872656164244275696c646572244f665669727475616c3b08000e0100155265646b616c652d5669727475616c5468726561640b001000110700120c001300140100226a6176612f6c616e672f546872656164244275696c646572244f665669727475616c0100046e616d65010038284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f546872656164244275696c646572244f665669727475616c3b0b001000160c001700180100057374617274010028284c6a6176612f6c616e672f52756e6e61626c653b294c6a6176612f6c616e672f5468726561643b07001a0100296f72672f7265646b616c652f7574696c2f416e6f6e796d6f75735669727475616c4578656375746f7207001c01001d6a6176612f7574696c2f636f6e63757272656e742f4578656375746f72010004436f646501000f4c696e654e756d6265725461626c650100124c6f63616c5661726961626c655461626c650100047468697301002b4c6f72672f7265646b616c652f7574696c2f416e6f6e796d6f75735669727475616c4578656375746f723b01000765786563757465010017284c6a6176612f6c616e672f52756e6e61626c653b2956010001740100144c6a6176612f6c616e672f52756e6e61626c653b0100104d6574686f64506172616d657465727301000a536f7572636546696c6501001d416e6f6e796d6f75735669727475616c4578656375746f722e6a61766101000c496e6e6572436c617373657307002b0100186a6176612f6c616e672f546872656164244275696c6465720100074275696c6465720100094f665669727475616c0021001900020001001b000000020001000500060001001d0000002f00010001000000052ab70001b100000002001e0000000600010000000e001f0000000c0001000000050020002100000001002200230002001d0000004a0002000200000012b80007120db9000f02002bb90015020057b100000002001e0000000a00020000001200110013001f00000016000200000012002000210000000000120024002500010026000000050100240000000200270000000200280029000000120002002a0008002c06090010002a002d0609";
|
||
|
||
private static final Executor virtualExecutorConsumer;
|
||
|
||
// org.redkale.util.SignalShutDown
|
||
private static final String consumerSignalShutdownBinary =
|
||
"cafebabe00000037006b0a0019003a090018003b07003c08003d08003e08003f0800400800410800420800430800440800450700460a000d00470a000d004807004907004a0a000d004b0a000d004c12000000500b001600510700520a0018005307005407005507005601001073687574646f776e436f6e73756d657201001d4c6a6176612f7574696c2f66756e6374696f6e2f436f6e73756d65723b0100095369676e61747572650100314c6a6176612f7574696c2f66756e6374696f6e2f436f6e73756d65723c4c6a6176612f6c616e672f537472696e673b3e3b0100063c696e69743e010003282956010004436f646501000f4c696e654e756d6265725461626c650100124c6f63616c5661726961626c655461626c65010004746869730100214c6f72672f7265646b616c652f7574696c2f5369676e616c53687574446f776e3b010006616363657074010020284c6a6176612f7574696c2f66756e6374696f6e2f436f6e73756d65723b29560100037369670100124c6a6176612f6c616e672f537472696e673b010004736967730100135b4c6a6176612f6c616e672f537472696e673b010008636f6e73756d65720100164c6f63616c5661726961626c65547970655461626c6501000d537461636b4d61705461626c6507002b0100104d6574686f64506172616d6574657273010034284c6a6176612f7574696c2f66756e6374696f6e2f436f6e73756d65723c4c6a6176612f6c616e672f537472696e673b3e3b295601000668616e646c65010014284c73756e2f6d6973632f5369676e616c3b29560100114c73756e2f6d6973632f5369676e616c3b010006736967737472010015284c6a6176612f6c616e672f4f626a6563743b295601007a4c6a6176612f6c616e672f4f626a6563743b4c6a6176612f7574696c2f66756e6374696f6e2f436f6e73756d65723c4c6a6176612f7574696c2f66756e6374696f6e2f436f6e73756d65723c4c6a6176612f6c616e672f537472696e673b3e3b3e3b4c73756e2f6d6973632f5369676e616c48616e646c65723b01000a536f7572636546696c650100135369676e616c53687574446f776e2e6a6176610c001f00200c001b001c0100106a6176612f6c616e672f537472696e670100034855500100045445524d010003494e54010004515549540100044b494c4c01000454535450010004555352310100045553523201000453544f5001000f73756e2f6d6973632f5369676e616c0c001f00570c003200580100136a6176612f6c616e672f457863657074696f6e0100136a6176612f6c616e672f5468726f7761626c650c0059005a0c005b005c010010426f6f7473747261704d6574686f64730f06005d08005e0c005f00600c0026003601001b6a6176612f7574696c2f66756e6374696f6e2f436f6e73756d65720c0026002701001f6f72672f7265646b616c652f7574696c2f5369676e616c53687574446f776e0100106a6176612f6c616e672f4f626a65637401001673756e2f6d6973632f5369676e616c48616e646c6572010015284c6a6176612f6c616e672f537472696e673b2956010043284c73756e2f6d6973632f5369676e616c3b4c73756e2f6d6973632f5369676e616c48616e646c65723b294c73756e2f6d6973632f5369676e616c48616e646c65723b0100076765744e616d6501001428294c6a6176612f6c616e672f537472696e673b0100096765744e756d6265720100032829490a00610062010005012c012c010100176d616b65436f6e63617457697468436f6e7374616e7473010038284c73756e2f6d6973632f5369676e616c3b4c6a6176612f6c616e672f537472696e673b49294c6a6176612f6c616e672f537472696e673b0700630c005f00670100246a6176612f6c616e672f696e766f6b652f537472696e67436f6e636174466163746f72790700690100064c6f6f6b757001000c496e6e6572436c6173736573010098284c6a6176612f6c616e672f696e766f6b652f4d6574686f6448616e646c6573244c6f6f6b75703b4c6a6176612f6c616e672f537472696e673b4c6a6176612f6c616e672f696e766f6b652f4d6574686f64547970653b4c6a6176612f6c616e672f537472696e673b5b4c6a6176612f6c616e672f4f626a6563743b294c6a6176612f6c616e672f696e766f6b652f43616c6c536974653b07006a0100256a6176612f6c616e672f696e766f6b652f4d6574686f6448616e646c6573244c6f6f6b757001001e6a6176612f6c616e672f696e766f6b652f4d6574686f6448616e646c657300210018001900020016001a00010002001b001c0001001d00000002001e00040001001f0020000100210000002f00010001000000052ab70001b10000000200220000000600010000000c00230000000c000100000005002400250000000100260027000300210000014a000400080000006f2a2bb500021009bd0003590312045359041205535905120653590612075359071208535908120953591006120a53591007120b53591008120c534d2c4e2dbe360403360515051504a200222d1505323a06bb000d591906b7000e2ab8000f57a700053a07840501a7ffdda700044db100020051005f006200100005006a006d0011000400220000002a000a0000001200050014003b001500510017005f00190062001800640015006a001c006d001b006e001d00230000002a000400510013002800290006003b002f002a002b00020000006f0024002500000000006f002c001c0001002d0000000c00010000006f002c001e0001002e000000470006ff0044000607001807001607002f07002f01010000ff001d000707001807001607002f07002f01010700030001070010fa0001ff000500020700180700160000420700110000300000000501002c0000001d0000000200310021003200330002002100000060000300030000001a2b2bb600122bb60013ba001400004d2ab400022cb900150200b10000000200220000000e000300000021000f00220019002300230000002000030000001a0024002500000000001a002800340001000f000b0035002900020030000000050100280000104100260036000200210000003300020002000000092a2bc00016b60017b10000000200220000000600010000000c00230000000c00010000000900240025000000300000000501002c10000004001d000000020037003800000002003900660000000a00010064006800650019004d000000080001004e0001004f";
|
||
|
||
private static final Consumer<Consumer<String>> signalShutdownConsumer;
|
||
|
||
// org.redkale.util.AnonymousUnsafe
|
||
private static final String funcAnonymousUnsafeBinary =
|
||
"cafebabe0000003701710a000200030700040c000500060100106a6176612f6c616e672f4f626a6563740100063c696e69743e01000328295607000801000f73756e2f6d6973632f556e7361666509000a000b07000c0c000d000e0100206f72672f7265646b616c652f7574696c2f416e6f6e796d6f7573556e73616665010006756e736166650100114c73756e2f6d6973632f556e736166653b0a000700100c00110012010006676574496e74010016284c6a6176612f6c616e672f4f626a6563743b4a29490a000700140c00150016010006707574496e74010017284c6a6176612f6c616e672f4f626a6563743b4a4929560a000700180c0019001a0100096765744f626a656374010027284c6a6176612f6c616e672f4f626a6563743b4a294c6a6176612f6c616e672f4f626a6563743b0a0007001c0c001d001e0100097075744f626a656374010028284c6a6176612f6c616e672f4f626a6563743b4a4c6a6176612f6c616e672f4f626a6563743b29560a000700200c0021002201000a676574426f6f6c65616e010016284c6a6176612f6c616e672f4f626a6563743b4a295a0a000700240c0025002601000a707574426f6f6c65616e010017284c6a6176612f6c616e672f4f626a6563743b4a5a29560a000700280c0029002a01000767657442797465010016284c6a6176612f6c616e672f4f626a6563743b4a29420a0007002c0c002d002e01000770757442797465010017284c6a6176612f6c616e672f4f626a6563743b4a4229560a000700300c0031003201000867657453686f7274010016284c6a6176612f6c616e672f4f626a6563743b4a29530a000700340c0035003601000870757453686f7274010017284c6a6176612f6c616e672f4f626a6563743b4a5329560a000700380c0039003a01000767657443686172010016284c6a6176612f6c616e672f4f626a6563743b4a29430a0007003c0c003d003e01000770757443686172010017284c6a6176612f6c616e672f4f626a6563743b4a4329560a000700400c004100420100076765744c6f6e67010016284c6a6176612f6c616e672f4f626a6563743b4a294a0a000700440c004500460100077075744c6f6e67010017284c6a6176612f6c616e672f4f626a6563743b4a4a29560a000700480c0049004a010008676574466c6f6174010016284c6a6176612f6c616e672f4f626a6563743b4a29460a0007004c0c004d004e010008707574466c6f6174010017284c6a6176612f6c616e672f4f626a6563743b4a4629560a000700500c00510052010009676574446f75626c65010016284c6a6176612f6c616e672f4f626a6563743b4a29440a000700540c00550056010009707574446f75626c65010017284c6a6176612f6c616e672f4f626a6563743b4a4429560a000700580c00290059010004284a29420a0007005b0c002d005c010005284a4229560a0007005e0c0031005f010004284a29530a000700610c00350062010005284a5329560a000700640c00390065010004284a29430a000700670c003d0068010005284a4329560a0007006a0c0011006b010004284a29490a0007006d0c0015006e010005284a4929560a000700700c00410071010004284a294a0a000700730c00450074010005284a4a29560a000700760c00490077010004284a29460a000700790c004d007a010005284a4629560a0007007c0c0051007d010004284a29440a0007007f0c00550080010005284a4429560a000700820c0083007101000a676574416464726573730a000700850c0086007401000a707574416464726573730a000700880c0089007101000e616c6c6f636174654d656d6f72790a0007008b0c008c008d0100107265616c6c6f636174654d656d6f7279010005284a4a294a0a0007008f0c009000910100097365744d656d6f7279010018284c6a6176612f6c616e672f4f626a6563743b4a4a4229560a000700930c00900094010006284a4a4229560a000700960c0097009801000a636f70794d656d6f727901002a284c6a6176612f6c616e672f4f626a6563743b4a4c6a6176612f6c616e672f4f626a6563743b4a4a29560a0007009a0c0097009b010006284a4a4a29560a0007009d0c009e009f01000a667265654d656d6f7279010004284a29560a000700a10c00a200a30100116f626a6563744669656c644f666673657401001c284c6a6176612f6c616e672f7265666c6563742f4669656c643b294a0a000700a50c00a600a30100117374617469634669656c644f66667365740a000700a80c00a900aa01000f7374617469634669656c644261736501002d284c6a6176612f6c616e672f7265666c6563742f4669656c643b294c6a6176612f6c616e672f4f626a6563743b0a000700ac0c00ad00ae01000f6172726179426173654f6666736574010014284c6a6176612f6c616e672f436c6173733b29490a000700b00c00b100ae01000f6172726179496e6465785363616c650a000700b30c00b400b501000b6164647265737353697a650100032829490a000700b70c00b800b50100087061676553697a650a000700ba0c00bb00bc010010616c6c6f63617465496e7374616e6365010025284c6a6176612f6c616e672f436c6173733b294c6a6176612f6c616e672f4f626a6563743b0a000700be0c00bf00c001000e7468726f77457863657074696f6e010018284c6a6176612f6c616e672f5468726f7761626c653b29560a000700c20c00c300c4010014636f6d70617265416e64537761704f626a65637401003a284c6a6176612f6c616e672f4f626a6563743b4a4c6a6176612f6c616e672f4f626a6563743b4c6a6176612f6c616e672f4f626a6563743b295a0a000700c60c00c700c8010011636f6d70617265416e6453776170496e74010018284c6a6176612f6c616e672f4f626a6563743b4a4949295a0a000700ca0c00cb00cc010012636f6d70617265416e64537761704c6f6e67010018284c6a6176612f6c616e672f4f626a6563743b4a4a4a295a0a000700ce0c00cf001a0100116765744f626a656374566f6c6174696c650a000700d10c00d2001e0100117075744f626a656374566f6c6174696c650a000700d40c00d5001201000e676574496e74566f6c6174696c650a000700d70c00d8001601000e707574496e74566f6c6174696c650a000700da0c00db0022010012676574426f6f6c65616e566f6c6174696c650a000700dd0c00de0026010012707574426f6f6c65616e566f6c6174696c650a000700e00c00e1002a01000f67657442797465566f6c6174696c650a000700e30c00e4002e01000f70757442797465566f6c6174696c650a000700e60c00e7003201001067657453686f7274566f6c6174696c650a000700e90c00ea003601001070757453686f7274566f6c6174696c650a000700ec0c00ed003a01000f67657443686172566f6c6174696c650a000700ef0c00f0003e01000f70757443686172566f6c6174696c650a000700f20c00f3004201000f6765744c6f6e67566f6c6174696c650a000700f50c00f6004601000f7075744c6f6e67566f6c6174696c650a000700f80c00f9004a010010676574466c6f6174566f6c6174696c650a000700fb0c00fc004e010010707574466c6f6174566f6c6174696c650a000700fe0c00ff0052010011676574446f75626c65566f6c6174696c650a000701010c01020056010011707574446f75626c65566f6c6174696c650a000701040c0105001e0100107075744f7264657265644f626a6563740a000701070c0108001601000d7075744f726465726564496e740a0007010a0c010b004601000e7075744f7264657265644c6f6e670a0007010d0c010e010f010006756e7061726b010015284c6a6176612f6c616e672f4f626a6563743b29560a000701110c011201130100047061726b010005285a4a29560a000701150c0116011701000e6765744c6f616441766572616765010006285b444929490a000701190c011a011b01000c676574416e64416464496e74010017284c6a6176612f6c616e672f4f626a6563743b4a4929490a0007011d0c011e011f01000d676574416e644164644c6f6e67010017284c6a6176612f6c616e672f4f626a6563743b4a4a294a0a000701210c0122011b01000c676574416e64536574496e740a000701240c0125011f01000d676574416e645365744c6f6e670a000701270c0128012901000f676574416e645365744f626a656374010039284c6a6176612f6c616e672f4f626a6563743b4a4c6a6176612f6c616e672f4f626a6563743b294c6a6176612f6c616e672f4f626a6563743b0a0007012b0c012c00060100096c6f616446656e63650a0007012e0c012f000601000a73746f726546656e63650a000701310c0132000601000966756c6c46656e63650a000701340c0135013601000d696e766f6b65436c65616e6572010018284c6a6176612f6e696f2f427974654275666665723b29560701380100176f72672f7265646b616c652f7574696c2f556e73616665010004436f646501000f4c696e654e756d6265725461626c650100124c6f63616c5661726961626c655461626c65010004746869730100224c6f72672f7265646b616c652f7574696c2f416e6f6e796d6f7573556e736166653b0100036f626a0100124c6a6176612f6c616e672f4f626a6563743b0100104d6574686f64506172616d65746572730100016f0100066f66667365740100014a01000178010001490100015a010001420100015301000143010001460100014401000761646472657373010005627974657301000576616c7565010007737263426173650100097372634f6666736574010008646573744261736501000a646573744f666673657401000a7372634164647265737301000b6465737441646472657373010001660100194c6a6176612f6c616e672f7265666c6563742f4669656c643b01000a6172726179436c6173730100114c6a6176612f6c616e672f436c6173733b0100164c6f63616c5661726961626c65547970655461626c650100144c6a6176612f6c616e672f436c6173733c2a3e3b0100095369676e6174757265010017284c6a6176612f6c616e672f436c6173733c2a3e3b2949010003636c7301000a457863657074696f6e730701600100206a6176612f6c616e672f496e7374616e74696174696f6e457863657074696f6e010028284c6a6176612f6c616e672f436c6173733c2a3e3b294c6a6176612f6c616e672f4f626a6563743b01000265650100154c6a6176612f6c616e672f5468726f7761626c653b010008657870656374656401000674687265616401000a69734162736f6c75746501000474696d650100076c6f61646176670100025b440100066e656c656d7301000564656c74610100086e657756616c756501000c6469726563744275666665720100154c6a6176612f6e696f2f427974654275666665723b01000a536f7572636546696c65010014416e6f6e796d6f7573556e736166652e6a6176610021000a00020001013700010012000d000e0000005700010005010f0002013900000049000200020000000d2ab700012a2bc00007b50009b100000002013a0000000e00030000000a0004000b000c000c013b0000001600020000000d013c013d00000000000d013e013f000101400000000501013e00000001001100120002013900000048000400040000000a2ab400092b20b6000fac00000002013a00000006000100000010013b0000002000030000000a013c013d00000000000a0141013f00010000000a0142014300020140000000090201410000014200000001001500160002013900000058000500050000000c2ab400092b201504b60013b100000002013a0000000a000200000015000b0016013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440145000401400000000d0301410000014200000144000000010019001a0002013900000048000400040000000a2ab400092b20b60017b000000002013a0000000600010000001a013b0000002000030000000a013c013d00000000000a0141013f00010000000a0142014300020140000000090201410000014200000001001d001e0002013900000058000500050000000c2ab400092b201904b6001bb100000002013a0000000a00020000001f000b0020013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c0144013f000401400000000d030141000001420000014400000001002100220002013900000048000400040000000a2ab400092b20b6001fac00000002013a00000006000100000024013b0000002000030000000a013c013d00000000000a0141013f00010000000a0142014300020140000000090201410000014200000001002500260002013900000058000500050000000c2ab400092b201504b60023b100000002013a0000000a000200000029000b002a013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440146000401400000000d0301410000014200000144000000010029002a0002013900000048000400040000000a2ab400092b20b60027ac00000002013a0000000600010000002e013b0000002000030000000a013c013d00000000000a0141013f00010000000a0142014300020140000000090201410000014200000001002d002e0002013900000058000500050000000c2ab400092b201504b6002bb100000002013a0000000a000200000033000b0034013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440147000401400000000d030141000001420000014400000001003100320002013900000048000400040000000a2ab400092b20b6002fac00000002013a00000006000100000038013b0000002000030000000a013c013d00000000000a0141013f00010000000a0142014300020140000000090201410000014200000001003500360002013900000058000500050000000c2ab400092b201504b60033b100000002013a0000000a00020000003d000b003e013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440148000401400000000d0301410000014200000144000000010039003a0002013900000048000400040000000a2ab400092b20b60037ac00000002013a00000006000100000042013b0000002000030000000a013c013d00000000000a0141013f00010000000a0142014300020140000000090201410000014200000001003d003e0002013900000058000500050000000c2ab400092b201504b6003bb100000002013a0000000a000200000047000b0048013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440149000401400000000d030141000001420000014400000001004100420002013900000048000400040000000a2ab400092b20b6003fad00000002013a0000000600010000004c013b0000002000030000000a013c013d00000000000a0141013f00010000000a0142014300020140000000090201410000014200000001004500460002013900000058000600060000000c2ab400092b201604b60043b100000002013a0000000a000200000051000b0052013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440143000401400000000d0301410000014200000144000000010049004a0002013900000048000400040000000a2ab400092b20b60047ae00000002013a00000006000100000056013b0000002000030000000a013c013d00000000000a0141013f00010000000a0142014300020140000000090201410000014200000001004d004e0002013900000058000500050000000c2ab400092b201704b6004bb100000002013a0000000a00020000005b000b005c013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c0144014a000401400000000d030141000001420000014400000001005100520002013900000048000400040000000a2ab400092b20b6004faf00000002013a00000006000100000060013b0000002000030000000a013c013d00000000000a0141013f00010000000a0142014300020140000000090201410000014200000001005500560002013900000058000600060000000c2ab400092b201804b60053b100000002013a0000000a000200000065000b0066013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c0144014b000401400000000d03014100000142000001440000000100290059000201390000003d00030003000000092ab400091fb60057ac00000002013a0000000600010000006a013b00000016000200000009013c013d000000000009014c0143000101400000000501014c00000001002d005c000201390000004c000400040000000a2ab400091f1db6005ab100000002013a0000000a00020000006f00090070013b0000002000030000000a013c013d00000000000a014c014300010000000a01440147000301400000000902014c00000144000000010031005f000201390000003d00030003000000092ab400091fb6005dac00000002013a00000006000100000074013b00000016000200000009013c013d000000000009014c0143000101400000000501014c0000000100350062000201390000004c000400040000000a2ab400091f1db60060b100000002013a0000000a0002000000790009007a013b0000002000030000000a013c013d00000000000a014c014300010000000a01440148000301400000000902014c000001440000000100390065000201390000003d00030003000000092ab400091fb60063ac00000002013a0000000600010000007e013b00000016000200000009013c013d000000000009014c0143000101400000000501014c00000001003d0068000201390000004c000400040000000a2ab400091f1db60066b100000002013a0000000a00020000008300090084013b0000002000030000000a013c013d00000000000a014c014300010000000a01440149000301400000000902014c00000144000000010011006b000201390000003d00030003000000092ab400091fb60069ac00000002013a00000006000100000088013b00000016000200000009013c013d000000000009014c0143000101400000000501014c000000010015006e000201390000004c000400040000000a2ab400091f1db6006cb100000002013a0000000a00020000008d0009008e013b0000002000030000000a013c013d00000000000a014c014300010000000a01440145000301400000000902014c000001440000000100410071000201390000003d00030003000000092ab400091fb6006fad00000002013a00000006000100000092013b00000016000200000009013c013d000000000009014c0143000101400000000501014c0000000100450074000201390000004c000500050000000a2ab400091f21b60072b100000002013a0000000a00020000009700090098013b0000002000030000000a013c013d00000000000a014c014300010000000a01440143000301400000000902014c000001440000000100490077000201390000003d00030003000000092ab400091fb60075ae00000002013a0000000600010000009c013b00000016000200000009013c013d000000000009014c0143000101400000000501014c00000001004d007a000201390000004c000400040000000a2ab400091f25b60078b100000002013a0000000a0002000000a1000900a2013b0000002000030000000a013c013d00000000000a014c014300010000000a0144014a000301400000000902014c00000144000000010051007d000201390000003d00030003000000092ab400091fb6007baf00000002013a000000060001000000a6013b00000016000200000009013c013d000000000009014c0143000101400000000501014c0000000100550080000201390000004c000500050000000a2ab400091f29b6007eb100000002013a0000000a0002000000ab000900ac013b0000002000030000000a013c013d00000000000a014c014300010000000a0144014b000301400000000902014c000001440000000100830071000201390000003d00030003000000092ab400091fb60081ad00000002013a000000060001000000b0013b00000016000200000009013c013d000000000009014c0143000101400000000501014c0000000100860074000201390000004c000500050000000a2ab400091f21b60084b100000002013a0000000a0002000000b5000900b6013b0000002000030000000a013c013d00000000000a014c014300010000000a01440143000301400000000902014c000001440000000100890071000201390000003d00030003000000092ab400091fb60087ad00000002013a000000060001000000ba013b00000016000200000009013c013d000000000009014d0143000101400000000501014d00000001008c008d0002013900000048000500050000000a2ab400091f21b6008aad00000002013a000000060001000000bf013b0000002000030000000a013c013d00000000000a014c014300010000000a014d0143000301400000000902014c0000014d00000001009000910002013900000064000700070000000e2ab400092b2016041506b6008eb100000002013a0000000a0002000000c4000d00c5013b0000003400050000000e013c013d00000000000e0141013f00010000000e0142014300020000000e014d014300040000000e014e01470006014000000011040141000001420000014d0000014e00000001009000940002013900000058000600060000000c2ab400091f211505b60092b100000002013a0000000a0002000000c9000b00ca013b0000002a00040000000c013c013d00000000000c014c014300010000000c014d014300030000000c014e0147000501400000000d03014c0000014d0000014e0000000100970098000201390000007000090009000000102ab400092b20190416051607b60095b100000002013a0000000a0002000000ce000f00cf013b0000003e000600000010013c013d000000000010014f013f000100000010015001430002000000100151013f00040000001001520143000500000010014d0143000701400000001505014f0000015000000151000001520000014d000000010097009b0002013900000058000700070000000c2ab400091f211605b60099b100000002013a0000000a0002000000d3000b00d4013b0000002a00040000000c013c013d00000000000c0153014300010000000c0154014300030000000c014d0143000501400000000d030153000001540000014d00000001009e009f000201390000004100030003000000092ab400091fb6009cb100000002013a0000000a0002000000d8000800d9013b00000016000200000009013c013d000000000009014c0143000101400000000501014c0000000100a200a3000201390000003d00020002000000092ab400092bb600a0ad00000002013a000000060001000000dd013b00000016000200000009013c013d0000000000090155015600010140000000050101550000000100a600a3000201390000003d00020002000000092ab400092bb600a4ad00000002013a000000060001000000e2013b00000016000200000009013c013d0000000000090155015600010140000000050101550000000100a900aa000201390000003d00020002000000092ab400092bb600a7b000000002013a000000060001000000e7013b00000016000200000009013c013d0000000000090155015600010140000000050101550000000100ad00ae000301390000004f00020002000000092ab400092bb600abac00000003013a000000060001000000ec013b00000016000200000009013c013d00000000000901570158000101590000000c0001000000090157015a00010140000000050101570000015b00000002015c000100b100ae000301390000004f00020002000000092ab400092bb600afac00000003013a000000060001000000f1013b00000016000200000009013c013d00000000000901570158000101590000000c0001000000090157015a00010140000000050101570000015b00000002015c000100b400b5000101390000003200010001000000082ab40009b600b2ac00000002013a000000060001000000f6013b0000000c000100000008013c013d0000000100b800b5000101390000003200010001000000082ab40009b600b6ac00000002013a000000060001000000fb013b0000000c000100000008013c013d0000000100bb00bc000401390000004f00020002000000092ab400092bb600b9b000000003013a00000006000100000100013b00000016000200000009013c013d000000000009015d0158000101590000000c000100000009015d015a0001015e000000040001015f01400000000501015d0000015b000000020161000100bf00c0000201390000004100020002000000092ab400092bb600bdb100000002013a0000000a00020000010500080106013b00000016000200000009013c013d0000000000090162016300010140000000050101620000000100c300c40002013900000060000600060000000e2ab400092b2019041905b600c1ac00000002013a0000000600010000010a013b0000003400050000000e013c013d00000000000e0141013f00010000000e0142014300020000000e0164013f00040000000e0144013f00050140000000110401410000014200000164000001440000000100c700c80002013900000060000600060000000e2ab400092b2015041505b600c5ac00000002013a0000000600010000010f013b0000003400050000000e013c013d00000000000e0141013f00010000000e0142014300020000000e0164014500040000000e0144014500050140000000110401410000014200000164000001440000000100cb00cc0002013900000060000800080000000e2ab400092b2016041606b600c9ac00000002013a00000006000100000114013b0000003400050000000e013c013d00000000000e0141013f00010000000e0142014300020000000e0164014300040000000e0144014300060140000000110401410000014200000164000001440000000100cf001a0002013900000048000400040000000a2ab400092b20b600cdb000000002013a00000006000100000119013b0000002000030000000a013c013d00000000000a0141013f00010000000a014201430002014000000009020141000001420000000100d2001e0002013900000058000500050000000c2ab400092b201904b600d0b100000002013a0000000a00020000011e000b011f013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c0144013f000401400000000d03014100000142000001440000000100d500120002013900000048000400040000000a2ab400092b20b600d3ac00000002013a00000006000100000123013b0000002000030000000a013c013d00000000000a0141013f00010000000a014201430002014000000009020141000001420000000100d800160002013900000058000500050000000c2ab400092b201504b600d6b100000002013a0000000a000200000128000b0129013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440145000401400000000d03014100000142000001440000000100db00220002013900000048000400040000000a2ab400092b20b600d9ac00000002013a0000000600010000012d013b0000002000030000000a013c013d00000000000a0141013f00010000000a014201430002014000000009020141000001420000000100de00260002013900000058000500050000000c2ab400092b201504b600dcb100000002013a0000000a000200000132000b0133013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440146000401400000000d03014100000142000001440000000100e1002a0002013900000048000400040000000a2ab400092b20b600dfac00000002013a00000006000100000137013b0000002000030000000a013c013d00000000000a0141013f00010000000a014201430002014000000009020141000001420000000100e4002e0002013900000058000500050000000c2ab400092b201504b600e2b100000002013a0000000a00020000013c000b013d013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440147000401400000000d03014100000142000001440000000100e700320002013900000048000400040000000a2ab400092b20b600e5ac00000002013a00000006000100000141013b0000002000030000000a013c013d00000000000a0141013f00010000000a014201430002014000000009020141000001420000000100ea00360002013900000058000500050000000c2ab400092b201504b600e8b100000002013a0000000a000200000146000b0147013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440148000401400000000d03014100000142000001440000000100ed003a0002013900000048000400040000000a2ab400092b20b600ebac00000002013a0000000600010000014b013b0000002000030000000a013c013d00000000000a0141013f00010000000a014201430002014000000009020141000001420000000100f0003e0002013900000058000500050000000c2ab400092b201504b600eeb100000002013a0000000a000200000150000b0151013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440149000401400000000d03014100000142000001440000000100f300420002013900000048000400040000000a2ab400092b20b600f1ad00000002013a00000006000100000155013b0000002000030000000a013c013d00000000000a0141013f00010000000a014201430002014000000009020141000001420000000100f600460002013900000058000600060000000c2ab400092b201604b600f4b100000002013a0000000a00020000015a000b015b013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440143000401400000000d03014100000142000001440000000100f9004a0002013900000048000400040000000a2ab400092b20b600f7ae00000002013a0000000600010000015f013b0000002000030000000a013c013d00000000000a0141013f00010000000a014201430002014000000009020141000001420000000100fc004e0002013900000058000500050000000c2ab400092b201704b600fab100000002013a0000000a000200000164000b0165013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c0144014a000401400000000d03014100000142000001440000000100ff00520002013900000048000400040000000a2ab400092b20b600fdaf00000002013a00000006000100000169013b0000002000030000000a013c013d00000000000a0141013f00010000000a0142014300020140000000090201410000014200000001010200560002013900000058000600060000000c2ab400092b201804b60100b100000002013a0000000a00020000016e000b016f013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c0144014b000401400000000d0301410000014200000144000000010105001e0002013900000058000500050000000c2ab400092b201904b60103b100000002013a0000000a000200000173000b0174013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c0144013f000401400000000d030141000001420000014400000001010800160002013900000058000500050000000c2ab400092b201504b60106b100000002013a0000000a000200000178000b0179013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440145000401400000000d030141000001420000014400000001010b00460002013900000058000600060000000c2ab400092b201604b60109b100000002013a0000000a00020000017d000b017e013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c01440143000401400000000d030141000001420000014400000001010e010f000201390000004100020002000000092ab400092bb6010cb100000002013a0000000a00020000018200080183013b00000016000200000009013c013d0000000000090165013f00010140000000050101650000000101120113000201390000004c000400040000000a2ab400091b20b60110b100000002013a0000000a00020000018700090188013b0000002000030000000a013c013d00000000000a0166014600010000000a0167014300020140000000090201660000016700000001011601170002013900000048000300030000000a2ab400092b1cb60114ac00000002013a0000000600010000018c013b0000002000030000000a013c013d00000000000a0168016900010000000a016a014500020140000000090201680000016a00000001011a011b0002013900000054000500050000000c2ab400092b201504b60118ac00000002013a00000006000100000191013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c016b0145000401400000000d030141000001420000016b00000001011e011f0002013900000054000600060000000c2ab400092b201604b6011cad00000002013a00000006000100000196013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c016b0143000401400000000d030141000001420000016b000000010122011b0002013900000054000500050000000c2ab400092b201504b60120ac00000002013a0000000600010000019b013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c016c0145000401400000000d030141000001420000016c000000010125011f0002013900000054000600060000000c2ab400092b201604b60123ad00000002013a000000060001000001a0013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c016c0143000401400000000d030141000001420000016c00000001012801290002013900000054000500050000000c2ab400092b201904b60126b000000002013a000000060001000001a5013b0000002a00040000000c013c013d00000000000c0141013f00010000000c0142014300020000000c016c013f000401400000000d030141000001420000016c00000001012c0006000101390000003600010001000000082ab40009b6012ab100000002013a0000000a0002000001aa000701ab013b0000000c000100000008013c013d00000001012f0006000101390000003600010001000000082ab40009b6012db100000002013a0000000a0002000001af000701b0013b0000000c000100000008013c013d0000000101320006000101390000003600010001000000082ab40009b60130b100000002013a0000000a0002000001b4000701b5013b0000000c000100000008013c013d0000000101350136000201390000004100020002000000092ab400092bb60133b100000002013a0000000a0002000001b9000801ba013b00000016000200000009013c013d000000000009016d016e000101400000000501016d00000001016f000000020170";
|
||
|
||
private static final Unsafe unsafeInstance;
|
||
|
||
// -------------------------------------------------------------------------------
|
||
private static final Function<String, byte[]> strByteFunction;
|
||
|
||
private static final Function<StringBuilder, byte[]> sbByteFunction;
|
||
|
||
private static final Predicate<Object> strLatin1Function;
|
||
|
||
private static final ToLongFunction<Object> bufferAddrFunction;
|
||
|
||
private static final ReentrantLock clientLock = new ReentrantLock();
|
||
|
||
// 是否native-image运行环境
|
||
private static final boolean NATIVE_IMAGE_ENV =
|
||
"executable".equals(System.getProperty("org.graalvm.nativeimage.kind"));
|
||
|
||
private static HttpClient httpClient;
|
||
|
||
private static final ScheduledThreadPoolExecutor delayer;
|
||
|
||
// private static final javax.net.ssl.SSLContext DEFAULTSSL_CONTEXT;
|
||
// private static final javax.net.ssl.HostnameVerifier defaultVerifier = (s, ss) -> true;
|
||
static {
|
||
System.setProperty("jdk.httpclient.allowRestrictedHeaders", "host");
|
||
|
||
(delayer = new ScheduledThreadPoolExecutor(1, r -> {
|
||
Thread t = new Thread(r);
|
||
t.setDaemon(true);
|
||
t.setName("RedkaleFutureDelayScheduler");
|
||
return t;
|
||
}))
|
||
.setRemoveOnCancelPolicy(true);
|
||
|
||
Unsafe unsafe0 = null;
|
||
Function<String, byte[]> strByteFunction0 = null;
|
||
Function<StringBuilder, byte[]> sbByteFunction0 = null;
|
||
Predicate<Object> strLatin1Function0 = null;
|
||
ToLongFunction<Object> bufferAddrFunction0 = null;
|
||
Consumer<Consumer<String>> signalShutdownConsumer0 = null;
|
||
Function<Supplier, ThreadLocal> virtualThreadLocalFunction0 = null;
|
||
Function<String, ThreadFactory> virtualThreadFactoryFunction0 = null;
|
||
Function<String, ExecutorService> virtualPoolFunction0 = null;
|
||
Executor virtualExecutorConsumer0 = null;
|
||
|
||
if (!NATIVE_IMAGE_ENV) { // not native-image
|
||
try {
|
||
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||
{ // virtualThreadLocalFunction
|
||
Class<Function<Supplier, ThreadLocal>> virtualClazz = null;
|
||
try {
|
||
virtualClazz = (Class) loader.loadClass("org.redkale.util.AnonymousThreadLocal");
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
if (virtualClazz == null) {
|
||
try {
|
||
byte[] classBytes = hexToBin(functionThreadLocalBinary);
|
||
virtualClazz = (Class<Function<Supplier, ThreadLocal>>)
|
||
new ClassLoader(loader) {
|
||
public final Class<?> loadClass(String name, byte[] b) {
|
||
return defineClass(name, b, 0, b.length);
|
||
}
|
||
}.loadClass("org.redkale.util.AnonymousThreadLocal", classBytes);
|
||
RedkaleClassLoader.putDynClass(virtualClazz.getName(), classBytes, virtualClazz);
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
}
|
||
if (virtualClazz != null) {
|
||
try {
|
||
RedkaleClassLoader.putReflectionDeclaredConstructors(virtualClazz, virtualClazz.getName());
|
||
Supplier supplier = () -> null;
|
||
virtualThreadLocalFunction0 =
|
||
virtualClazz.getConstructor(Supplier.class).newInstance(supplier);
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
}
|
||
}
|
||
{ // virtualThreadFactoryFunction
|
||
Class<Function<String, ThreadFactory>> virtualClazz = null;
|
||
try {
|
||
virtualClazz = (Class) loader.loadClass("org.redkale.util.AnonymousThreadFactory");
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
if (virtualClazz == null) {
|
||
try {
|
||
byte[] classBytes = hexToBin(functionThreadFactoryBinary);
|
||
virtualClazz = (Class<Function<String, ThreadFactory>>)
|
||
new ClassLoader(loader) {
|
||
public final Class<?> loadClass(String name, byte[] b) {
|
||
return defineClass(name, b, 0, b.length);
|
||
}
|
||
}.loadClass("org.redkale.util.AnonymousThreadFactory", classBytes);
|
||
RedkaleClassLoader.putDynClass(virtualClazz.getName(), classBytes, virtualClazz);
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
}
|
||
if (virtualClazz != null) {
|
||
try {
|
||
RedkaleClassLoader.putReflectionDeclaredConstructors(virtualClazz, virtualClazz.getName());
|
||
Object[] initargs = new Object[] {null};
|
||
virtualThreadFactoryFunction0 =
|
||
virtualClazz.getConstructor(String.class).newInstance(initargs);
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
}
|
||
}
|
||
{ // virtualPoolFunction
|
||
Class<Function<String, ExecutorService>> virtualClazz = null;
|
||
try {
|
||
virtualClazz = (Class) loader.loadClass("org.redkale.util.AnonymousVirtualPoolFunction");
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
if (virtualClazz == null) {
|
||
try {
|
||
byte[] classBytes = hexToBin(functionVirtualPoolBinary);
|
||
virtualClazz = (Class<Function<String, ExecutorService>>)
|
||
new ClassLoader(loader) {
|
||
public final Class<?> loadClass(String name, byte[] b) {
|
||
return defineClass(name, b, 0, b.length);
|
||
}
|
||
}.loadClass("org.redkale.util.AnonymousVirtualPoolFunction", classBytes);
|
||
RedkaleClassLoader.putDynClass(virtualClazz.getName(), classBytes, virtualClazz);
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
}
|
||
if (virtualClazz != null) {
|
||
try {
|
||
RedkaleClassLoader.putReflectionDeclaredConstructors(virtualClazz, virtualClazz.getName());
|
||
virtualPoolFunction0 = virtualClazz.getConstructor().newInstance();
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
}
|
||
}
|
||
{ // virtualExecutorConsumer
|
||
Class<Executor> virtualClazz = null;
|
||
try {
|
||
virtualClazz = (Class) loader.loadClass("org.redkale.util.AnonymousVirtualExecutor");
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
if (virtualClazz == null) {
|
||
try {
|
||
byte[] classBytes = hexToBin(consumerVirtualExecutorBinary);
|
||
virtualClazz = (Class<Executor>)
|
||
new ClassLoader(loader) {
|
||
public final Class<?> loadClass(String name, byte[] b) {
|
||
return defineClass(name, b, 0, b.length);
|
||
}
|
||
}.loadClass("org.redkale.util.AnonymousVirtualExecutor", classBytes);
|
||
RedkaleClassLoader.putDynClass(virtualClazz.getName(), classBytes, virtualClazz);
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
}
|
||
if (virtualClazz != null) {
|
||
try {
|
||
RedkaleClassLoader.putReflectionDeclaredConstructors(virtualClazz, virtualClazz.getName());
|
||
virtualExecutorConsumer0 =
|
||
virtualClazz.getConstructor().newInstance();
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
}
|
||
}
|
||
{ // unsafe
|
||
Field f = String.class.getDeclaredField("value");
|
||
final Class unsafeClass = loader.loadClass("sun.misc.Unsafe");
|
||
final Field safeField = unsafeClass.getDeclaredField("theUnsafe");
|
||
RedkaleClassLoader.putReflectionField("sun.misc.Unsafe", safeField);
|
||
safeField.setAccessible(true);
|
||
final Object usafe = safeField.get(null);
|
||
|
||
Class<Unsafe> unsafeClazz1 = null;
|
||
try {
|
||
unsafeClazz1 = (Class) loader.loadClass("org.redkale.util.AnonymousUnsafe");
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
if (unsafeClazz1 == null) {
|
||
byte[] classBytes = hexToBin(funcAnonymousUnsafeBinary);
|
||
unsafeClazz1 = (Class<Unsafe>)
|
||
new ClassLoader(loader) {
|
||
public final Class<?> loadClass(String name, byte[] b) {
|
||
return defineClass(name, b, 0, b.length);
|
||
}
|
||
}.loadClass("org.redkale.util.AnonymousUnsafe", classBytes);
|
||
RedkaleClassLoader.putDynClass(unsafeClazz1.getName(), classBytes, unsafeClazz1);
|
||
}
|
||
RedkaleClassLoader.putReflectionDeclaredConstructors(
|
||
unsafeClazz1, unsafeClazz1.getName(), Object.class);
|
||
unsafe0 = unsafeClazz1.getConstructor(Object.class).newInstance(usafe);
|
||
|
||
final Unsafe unsafe = unsafe0;
|
||
final long fd1 = unsafe0.objectFieldOffset(f);
|
||
final long fd2 = unsafe0.objectFieldOffset(
|
||
StringBuilder.class.getSuperclass().getDeclaredField("value"));
|
||
final long fd3 = unsafe0.objectFieldOffset(String.class.getDeclaredField("coder"));
|
||
final long fd4 = unsafe0.objectFieldOffset(Buffer.class.getDeclaredField("address"));
|
||
Field cf = String.class.getDeclaredField("COMPACT_STRINGS");
|
||
strByteFunction0 = (String t) -> (byte[]) unsafe.getObject(t, fd1);
|
||
sbByteFunction0 = (StringBuilder t) -> (byte[]) unsafe.getObject(t, fd2);
|
||
final boolean compact = unsafe.getBoolean(String.class, unsafe0.staticFieldOffset(cf));
|
||
// LATIN1:0 UTF16:1
|
||
strLatin1Function0 = compact ? (Object t) -> unsafe.getByte(t, fd3) == 0 : (Object t) -> false;
|
||
bufferAddrFunction0 = (Object t) -> unsafe.getLong(t, fd4);
|
||
}
|
||
{ // signalShutdown
|
||
Class<Consumer<Consumer<String>>> shutdownClazz1 = null;
|
||
try {
|
||
shutdownClazz1 = (Class) loader.loadClass("org.redkale.util.SignalShutDown");
|
||
} catch (Throwable t) {
|
||
// do nothing
|
||
}
|
||
if (shutdownClazz1 == null) {
|
||
byte[] classBytes = hexToBin(consumerSignalShutdownBinary);
|
||
shutdownClazz1 = (Class<Consumer<Consumer<String>>>)
|
||
new ClassLoader(loader) {
|
||
public final Class<?> loadClass(String name, byte[] b) {
|
||
return defineClass(name, b, 0, b.length);
|
||
}
|
||
}.loadClass("org.redkale.util.SignalShutDown", classBytes);
|
||
RedkaleClassLoader.putDynClass(shutdownClazz1.getName(), classBytes, shutdownClazz1);
|
||
RedkaleClassLoader.putReflectionDeclaredConstructors(shutdownClazz1, shutdownClazz1.getName());
|
||
signalShutdownConsumer0 =
|
||
shutdownClazz1.getConstructor().newInstance();
|
||
}
|
||
}
|
||
} catch (Throwable e) { // 不会发生
|
||
// do nothing
|
||
}
|
||
}
|
||
unsafeInstance = unsafe0;
|
||
strByteFunction = strByteFunction0;
|
||
sbByteFunction = sbByteFunction0;
|
||
strLatin1Function = strLatin1Function0;
|
||
bufferAddrFunction = bufferAddrFunction0;
|
||
signalShutdownConsumer = signalShutdownConsumer0;
|
||
virtualPoolFunction = virtualPoolFunction0;
|
||
virtualThreadLocalFunction = virtualThreadLocalFunction0;
|
||
virtualThreadFactoryFunction = virtualThreadFactoryFunction0;
|
||
virtualExecutorConsumer = virtualExecutorConsumer0;
|
||
|
||
// try {
|
||
// DEFAULTSSL_CONTEXT = javax.net.ssl.SSLContext.getInstance("SSL");
|
||
// DEFAULTSSL_CONTEXT.init(null, new javax.net.ssl.TrustManager[]{new
|
||
// javax.net.ssl.X509TrustManager() {
|
||
// @Override
|
||
// public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||
// return null;
|
||
// }
|
||
//
|
||
// @Override
|
||
// public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
|
||
// throws java.security.cert.CertificateException {
|
||
// }
|
||
//
|
||
// @Override
|
||
// public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
|
||
// throws java.security.cert.CertificateException {
|
||
// }
|
||
// }}, null);
|
||
// } catch (Exception e) {
|
||
// throw new RedkaleException(e); //不会发生
|
||
// }
|
||
}
|
||
|
||
private Utility() {}
|
||
|
||
public static Unsafe unsafe() {
|
||
return unsafeInstance;
|
||
}
|
||
|
||
public static int cpus() {
|
||
return CPUS;
|
||
}
|
||
|
||
public static boolean inNativeImage() {
|
||
return NATIVE_IMAGE_ENV;
|
||
}
|
||
|
||
public static Function<String, ExecutorService> virtualExecutorFunction() {
|
||
return virtualPoolFunction;
|
||
}
|
||
|
||
public static <T> ThreadLocal<T> withInitialThreadLocal(Supplier<T> supplier) {
|
||
return virtualThreadLocalFunction == null
|
||
? ThreadLocal.withInitial(supplier)
|
||
: virtualThreadLocalFunction.apply(supplier);
|
||
}
|
||
|
||
public static Function<String, ThreadFactory> virtualFactoryFunction() {
|
||
return virtualThreadFactoryFunction;
|
||
}
|
||
|
||
public static ThreadFactory newThreadFactory(final String name) {
|
||
if (virtualThreadFactoryFunction == null) {
|
||
if (isEmpty(name) || !name.contains("%s")) {
|
||
return (Runnable r) -> {
|
||
final Thread t = isEmpty(name) ? new Thread(r) : new Thread(r, name);
|
||
t.setDaemon(true);
|
||
return t;
|
||
};
|
||
} else {
|
||
AtomicInteger counter = new AtomicInteger();
|
||
return (Runnable r) -> {
|
||
final Thread t = new Thread(r, String.format(name, counter.incrementAndGet()));
|
||
t.setDaemon(true);
|
||
return t;
|
||
};
|
||
}
|
||
} else { // 虚拟线程工厂
|
||
return virtualThreadFactoryFunction.apply(
|
||
isEmpty(name)
|
||
? null
|
||
: (name.contains("%s") ? String.format(name, "Virtual") : (name + "-Virtual")));
|
||
}
|
||
}
|
||
|
||
public static ScheduledThreadPoolExecutor newScheduledExecutor(int corePoolSize) {
|
||
ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(corePoolSize, newThreadFactory(null));
|
||
scheduler.setRemoveOnCancelPolicy(true);
|
||
return scheduler;
|
||
}
|
||
|
||
public static ScheduledThreadPoolExecutor newScheduledExecutor(int corePoolSize, String name) {
|
||
ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(corePoolSize, newThreadFactory(name));
|
||
scheduler.setRemoveOnCancelPolicy(true);
|
||
return scheduler;
|
||
}
|
||
|
||
public static ScheduledThreadPoolExecutor newScheduledExecutor(
|
||
int corePoolSize, String name, RejectedExecutionHandler handler) {
|
||
ScheduledThreadPoolExecutor scheduler =
|
||
new ScheduledThreadPoolExecutor(corePoolSize, newThreadFactory(name), handler);
|
||
scheduler.setRemoveOnCancelPolicy(true);
|
||
return scheduler;
|
||
}
|
||
|
||
public static Consumer<Consumer<String>> signalShutdownConsumer() {
|
||
return signalShutdownConsumer;
|
||
}
|
||
|
||
public static IntFunction<Serializable[]> serialArrayFunc() {
|
||
return serialArrayFunc;
|
||
}
|
||
|
||
public static IntFunction<CompletableFuture[]> futureArrayFunc() {
|
||
return futureArrayFunc;
|
||
}
|
||
|
||
public static Executor defaultExecutor() {
|
||
return virtualExecutorConsumer == null ? defaultExecutorConsumer : virtualExecutorConsumer;
|
||
}
|
||
|
||
/**
|
||
* 构建method的唯一key,用于遍历类及父类的所有方法,key过滤重载方法
|
||
*
|
||
* @param method 方法
|
||
* @return key
|
||
*/
|
||
public static String methodKey(Method method) {
|
||
StringBuilder sb = new StringBuilder();
|
||
sb.append(method.getName());
|
||
sb.append('-').append(method.getParameterCount());
|
||
for (Class c : method.getParameterTypes()) {
|
||
sb.append('-').append(c.getName());
|
||
}
|
||
return sb.toString();
|
||
}
|
||
|
||
/**
|
||
* 返回第一个不为null的对象
|
||
*
|
||
* @param <T> 泛型
|
||
* @param val1 对象1
|
||
* @param val2 对象2
|
||
* @return 可用对象,可能返回null
|
||
*/
|
||
public static <T> T orElse(T val1, T val2) {
|
||
return val1 == null ? val2 : val1;
|
||
}
|
||
|
||
/**
|
||
* 返回第一个不为null的对象
|
||
*
|
||
* @param <T> 泛型
|
||
* @param vals 对象集合
|
||
* @return 可用对象,可能返回null
|
||
*/
|
||
public static <T> T orElse(T... vals) {
|
||
for (T t : vals) {
|
||
if (t != null) {
|
||
return t;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public static void execute(Runnable task) {
|
||
if (virtualExecutorConsumer != null) {
|
||
virtualExecutorConsumer.execute(task);
|
||
} else {
|
||
task.run();
|
||
}
|
||
}
|
||
|
||
public static void sleep(long millis) {
|
||
try {
|
||
Thread.sleep(millis);
|
||
} catch (InterruptedException ie) {
|
||
Thread.currentThread().interrupt();
|
||
}
|
||
}
|
||
|
||
public static boolean isAbstractOrInterface(Class clazz) {
|
||
return clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers());
|
||
}
|
||
|
||
public static String readFieldName(LambdaFunction func) {
|
||
return readLambdaFieldName(func);
|
||
}
|
||
|
||
public static String readFieldName(LambdaBiConsumer consumer) {
|
||
return readLambdaFieldName(consumer);
|
||
}
|
||
|
||
public static Class readClassName(LambdaBiConsumer consumer) {
|
||
return readLambdaClassName(consumer);
|
||
}
|
||
|
||
public static String readFieldName(LambdaSupplier func) {
|
||
return readLambdaFieldName(func);
|
||
}
|
||
|
||
public static Class readClassName(LambdaSupplier func) {
|
||
return readLambdaClassName(func);
|
||
}
|
||
|
||
private static String readLambdaFieldName(Serializable func) {
|
||
if (!func.getClass().isSynthetic()) { // 必须是Lambda表达式的合成类
|
||
throw new RedkaleException("Not a synthetic lambda class");
|
||
}
|
||
return lambdaFieldNameCache.computeIfAbsent(func.getClass(), clazz -> {
|
||
try {
|
||
MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(func.getClass(), MethodHandles.lookup());
|
||
MethodHandle mh =
|
||
lookup.findVirtual(func.getClass(), "writeReplace", MethodType.methodType(Object.class));
|
||
String methodName = ((java.lang.invoke.SerializedLambda) mh.invoke(func)).getImplMethodName();
|
||
return readFieldName(methodName);
|
||
} catch (Throwable e) {
|
||
return readLambdaFieldNameFromBytes(func);
|
||
}
|
||
});
|
||
}
|
||
|
||
private static String readLambdaFieldNameFromBytes(Serializable func) {
|
||
try {
|
||
ObjectWriteStream out = new ObjectWriteStream(new ByteArrayOutputStream());
|
||
out.writeObject(func);
|
||
out.close();
|
||
String methodName = out.methodNameReference.get();
|
||
if (methodName != null) {
|
||
return readFieldName(methodName);
|
||
} else {
|
||
// native-image环境下获取不到methodName
|
||
throw new RedkaleException("cannot found method-name from lambda " + func);
|
||
}
|
||
} catch (IOException e) {
|
||
throw new RedkaleException(e);
|
||
}
|
||
}
|
||
|
||
private static Class readLambdaClassName(Serializable func) {
|
||
if (!func.getClass().isSynthetic()) { // 必须是Lambda表达式的合成类
|
||
throw new RedkaleException("Not a synthetic lambda class");
|
||
}
|
||
return lambdaClassNameCache.computeIfAbsent(func.getClass(), clazz -> {
|
||
try {
|
||
MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(func.getClass(), MethodHandles.lookup());
|
||
MethodHandle mh =
|
||
lookup.findVirtual(func.getClass(), "writeReplace", MethodType.methodType(Object.class));
|
||
String methodName = ((java.lang.invoke.SerializedLambda) mh.invoke(func)).getImplMethodName();
|
||
String className = methodName.contains("lambda$")
|
||
? org.redkale.asm.Type.getReturnType(((java.lang.invoke.SerializedLambda) mh.invoke(func))
|
||
.getInstantiatedMethodType())
|
||
.getClassName()
|
||
: ((java.lang.invoke.SerializedLambda) mh.invoke(func))
|
||
.getImplClass()
|
||
.replace('/', '.');
|
||
return (Class) Thread.currentThread().getContextClassLoader().loadClass(className);
|
||
} catch (ClassNotFoundException ex) {
|
||
throw new RedkaleException(ex);
|
||
} catch (Throwable e) {
|
||
return readLambdaClassNameFromBytes(func);
|
||
}
|
||
});
|
||
}
|
||
|
||
private static Class readLambdaClassNameFromBytes(Serializable func) {
|
||
try {
|
||
ObjectWriteStream out = new ObjectWriteStream(new ByteArrayOutputStream());
|
||
out.writeObject(func);
|
||
out.close();
|
||
String className = out.classNameReference.get();
|
||
if (className != null) {
|
||
return (Class) Thread.currentThread().getContextClassLoader().loadClass(className);
|
||
} else {
|
||
// native-image环境下获取不到methodName
|
||
throw new RedkaleException("cannot found method-name from lambda " + func);
|
||
}
|
||
} catch (Exception e) {
|
||
throw new RedkaleException(e);
|
||
}
|
||
}
|
||
|
||
static String readFieldName(String methodName) {
|
||
String name;
|
||
if (methodName.startsWith("is")) {
|
||
name = methodName.substring(2);
|
||
} else if (methodName.startsWith("get") || methodName.startsWith("set")) {
|
||
name = methodName.substring(3);
|
||
} else {
|
||
name = methodName;
|
||
}
|
||
if (name.length() < 2) {
|
||
return name.toLowerCase(Locale.ENGLISH);
|
||
} else if (Character.isUpperCase(name.charAt(1))) {
|
||
return name;
|
||
} else {
|
||
return name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
|
||
}
|
||
}
|
||
|
||
static class ObjectWriteStream extends ObjectOutputStream {
|
||
|
||
public final ObjectRef<String> methodNameReference = new ObjectRef<>();
|
||
|
||
public final ObjectRef<String> classNameReference = new ObjectRef<>();
|
||
|
||
public ObjectWriteStream(OutputStream out) throws IOException {
|
||
super(out);
|
||
}
|
||
|
||
@Override
|
||
protected Object replaceObject(Object obj) throws IOException {
|
||
if (obj instanceof java.lang.invoke.SerializedLambda) {
|
||
String methodName = ((java.lang.invoke.SerializedLambda) obj).getImplMethodName();
|
||
methodNameReference.set(methodName);
|
||
java.lang.invoke.SerializedLambda sl = (java.lang.invoke.SerializedLambda) obj;
|
||
String className = methodName.contains("lambda$")
|
||
? org.redkale.asm.Type.getReturnType(sl.getInstantiatedMethodType())
|
||
.getClassName()
|
||
: sl.getImplClass().replace('/', '.');
|
||
classNameReference.set(className);
|
||
}
|
||
return super.replaceObject(obj);
|
||
}
|
||
|
||
@Override
|
||
public boolean enableReplaceObject(boolean enable) throws SecurityException {
|
||
return super.enableReplaceObject(enable);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @param value from which next positive power of two will be found.
|
||
* @return the next positive power of 2, this value if it is a power of 2. Negative values are mapped to 1.
|
||
* @throws IllegalArgumentException is value is more than MAX_POW2 or less than 0
|
||
*/
|
||
public static int roundToPowerOfTwo(final int value) {
|
||
if (value > MAX_POW2) {
|
||
throw new IllegalArgumentException(
|
||
"There is no larger power of 2 int for value:" + value + " since it exceeds 2^31.");
|
||
}
|
||
if (value < 0) {
|
||
throw new IllegalArgumentException("Given value:" + value + ". Expecting value >= 0.");
|
||
}
|
||
return 1 << (32 - Integer.numberOfLeadingZeros(value - 1));
|
||
}
|
||
|
||
public static boolean isRecordGetter(Method method) {
|
||
return isRecordGetter(method.getDeclaringClass(), method);
|
||
}
|
||
|
||
public static boolean isRecordGetter(Class clazz, Method method) {
|
||
if (JAVA_RECORD_CLASS == null) {
|
||
return false;
|
||
}
|
||
if (method.getReturnType() == void.class) {
|
||
return false;
|
||
}
|
||
if (method.getParameterCount() != 0) {
|
||
return false;
|
||
}
|
||
if (method.getName().equals("getClass")) {
|
||
return false;
|
||
}
|
||
Class clz = (clazz == null ? method.getDeclaringClass() : clazz);
|
||
if (!JAVA_RECORD_CLASS.isAssignableFrom(clz)) {
|
||
return false;
|
||
}
|
||
try {
|
||
return clz.getDeclaredField(method.getName()).getType() == method.getReturnType();
|
||
} catch (Throwable t) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public static <T> CompletableFuture<T> orTimeout(
|
||
CompletableFuture future, Supplier<String> errMsgFunc, Duration timeout) {
|
||
return orTimeout(future, errMsgFunc, timeout.toMillis(), TimeUnit.MILLISECONDS);
|
||
}
|
||
|
||
public static <T> CompletableFuture<T> orTimeout(
|
||
CompletableFuture future, Supplier<String> errMsgFunc, long timeout, TimeUnit unit) {
|
||
if (future == null) {
|
||
return future;
|
||
}
|
||
final ScheduledFuture<?> sf = delayer.schedule(
|
||
() -> {
|
||
if (!future.isDone()) {
|
||
String msg = errMsgFunc == null ? null : errMsgFunc.get();
|
||
future.completeExceptionally(msg == null ? new TimeoutException(msg) : new TimeoutException());
|
||
}
|
||
},
|
||
timeout,
|
||
unit);
|
||
return future.whenComplete((v, t) -> {
|
||
if (t == null && !sf.isDone()) {
|
||
sf.cancel(false);
|
||
}
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<T> completeOnTimeout(CompletableFuture future, T value, Duration timeout) {
|
||
return completeOnTimeout(future, value, timeout.toMillis(), TimeUnit.MILLISECONDS);
|
||
}
|
||
|
||
public static <T> CompletableFuture<T> completeOnTimeout(
|
||
CompletableFuture future, T value, long timeout, TimeUnit unit) {
|
||
return future.completeOnTimeout(value, timeout, unit);
|
||
}
|
||
|
||
public static <T> CompletableFuture<T[]> allOfFutures(List<CompletableFuture<T>> list, IntFunction<T[]> func) {
|
||
CompletableFuture<T>[] futures = list.toArray(futureArrayFunc);
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
T[] array = func.apply(size);
|
||
for (int i = 0; i < size; i++) {
|
||
array[i] = futures[i].join();
|
||
}
|
||
return array;
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<T[]> allOfFutures(Stream<CompletableFuture<T>> stream, IntFunction<T[]> func) {
|
||
CompletableFuture<T>[] futures = stream.toArray(futureArrayFunc);
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
T[] array = func.apply(size);
|
||
for (int i = 0; i < size; i++) {
|
||
array[i] = futures[i].join();
|
||
}
|
||
return array;
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<T[]> allOfFutures(CompletableFuture<T>[] futures, IntFunction<T[]> func) {
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
T[] array = func.apply(size);
|
||
for (int i = 0; i < size; i++) {
|
||
array[i] = futures[i].join();
|
||
}
|
||
return array;
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<T[]> allOfFutures(
|
||
List<CompletableFuture<T>> list, IntFunction<T[]> func, BiConsumer<Integer, T> consumer) {
|
||
CompletableFuture<T>[] futures = list.toArray(futureArrayFunc);
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
T[] array = func.apply(size);
|
||
for (int i = 0; i < size; i++) {
|
||
T val = futures[i].join();
|
||
consumer.accept(i, val);
|
||
array[i] = val;
|
||
}
|
||
return array;
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<T[]> allOfFutures(
|
||
Stream<CompletableFuture<T>> stream, IntFunction<T[]> func, BiConsumer<Integer, T> consumer) {
|
||
CompletableFuture<T>[] futures = stream.toArray(futureArrayFunc);
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
T[] array = func.apply(size);
|
||
for (int i = 0; i < size; i++) {
|
||
T val = futures[i].join();
|
||
consumer.accept(i, val);
|
||
array[i] = val;
|
||
}
|
||
return array;
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<T[]> allOfFutures(
|
||
CompletableFuture<T>[] futures, IntFunction<T[]> func, BiConsumer<Integer, T> consumer) {
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
T[] array = func.apply(size);
|
||
for (int i = 0; i < size; i++) {
|
||
T val = futures[i].join();
|
||
consumer.accept(i, val);
|
||
array[i] = val;
|
||
}
|
||
return array;
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<List<T>> allOfFutures(List<CompletableFuture<T>> list) {
|
||
CompletableFuture<T>[] futures = list.toArray(futureArrayFunc);
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
List<T> rs = new ArrayList<>(size);
|
||
for (int i = 0; i < size; i++) {
|
||
rs.add(futures[i].join());
|
||
}
|
||
return rs;
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<List<T>> allOfFutures(Stream<CompletableFuture<T>> stream) {
|
||
CompletableFuture<T>[] futures = stream.toArray(futureArrayFunc);
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
List<T> rs = new ArrayList<>(size);
|
||
for (int i = 0; i < size; i++) {
|
||
rs.add(futures[i].join());
|
||
}
|
||
return rs;
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<List<T>> allOfFutures(CompletableFuture<T>[] futures) {
|
||
if (futures.length == 1) {
|
||
return futures[0].thenApply(v -> {
|
||
List<T> rs = new ArrayList<>(1);
|
||
rs.add(v);
|
||
return rs;
|
||
});
|
||
}
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
List<T> rs = new ArrayList<>(size);
|
||
for (int i = 0; i < size; i++) {
|
||
rs.add(futures[i].join());
|
||
}
|
||
return rs;
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<List<T>> allOfFutures(
|
||
List<CompletableFuture<T>> list, BiConsumer<Integer, T> consumer) {
|
||
CompletableFuture<T>[] futures = list.toArray(futureArrayFunc);
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
List<T> rs = new ArrayList<>(size);
|
||
for (int i = 0; i < size; i++) {
|
||
T val = futures[i].join();
|
||
consumer.accept(i, val);
|
||
rs.add(val);
|
||
}
|
||
return rs;
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<List<T>> allOfFutures(
|
||
Stream<CompletableFuture<T>> stream, BiConsumer<Integer, T> consumer) {
|
||
CompletableFuture<T>[] futures = stream.toArray(futureArrayFunc);
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
List<T> rs = new ArrayList<>(size);
|
||
for (int i = 0; i < size; i++) {
|
||
T val = futures[i].join();
|
||
consumer.accept(i, val);
|
||
rs.add(val);
|
||
}
|
||
return rs;
|
||
});
|
||
}
|
||
|
||
public static <T> CompletableFuture<List<T>> allOfFutures(
|
||
CompletableFuture<T>[] futures, BiConsumer<Integer, T> consumer) {
|
||
if (futures.length == 1) {
|
||
return futures[0].thenApply(v -> {
|
||
List<T> rs = new ArrayList<>(1);
|
||
consumer.accept(0, v);
|
||
rs.add(v);
|
||
return rs;
|
||
});
|
||
}
|
||
return CompletableFuture.allOf(futures).thenApply(v -> {
|
||
int size = futures.length;
|
||
List<T> rs = new ArrayList<>(size);
|
||
for (int i = 0; i < size; i++) {
|
||
T val = futures[i].join();
|
||
consumer.accept(i, val);
|
||
rs.add(val);
|
||
}
|
||
return rs;
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 是否为数字字符串
|
||
*
|
||
* @param str 字符串
|
||
* @return 是否为数字字符串
|
||
*/
|
||
public static boolean isNumeric(String str) {
|
||
if (str == null || str.isEmpty()) {
|
||
return false;
|
||
}
|
||
int size = str.length();
|
||
for (int i = 0; i < size; i++) {
|
||
if (!Character.isDigit(str.charAt(i))) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 是否为空白
|
||
*
|
||
* @param str 字符串
|
||
* @return 是否为空白
|
||
*/
|
||
public static boolean isBlank(String str) {
|
||
return str == null || str.isEmpty() || str.isBlank();
|
||
}
|
||
|
||
/**
|
||
* 是否为空白
|
||
*
|
||
* @param str 字符串
|
||
* @param fromIndex 起始位置
|
||
* @param toIndex 结束位置
|
||
* @return 是否为空白
|
||
*/
|
||
public static boolean isBlank(String str, int fromIndex, int toIndex) {
|
||
if (str == null || str.isEmpty()) {
|
||
return true;
|
||
}
|
||
for (int i = fromIndex; i < toIndex; i++) {
|
||
char ch = str.charAt(i);
|
||
if (ch != ' ' && ch != '\t' && !Character.isWhitespace(ch)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 字符串是否至少一个为空白
|
||
*
|
||
* @param strs 字符串集合
|
||
* @return 是否为空白
|
||
*/
|
||
public static boolean isAnyBlank(String... strs) {
|
||
if (strs == null || strs.length == 0) {
|
||
return false;
|
||
}
|
||
for (String str : strs) {
|
||
if (isBlank(str)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 是否不为空白
|
||
*
|
||
* @param str 字符串
|
||
* @return 是否不为空白
|
||
*/
|
||
public static boolean isNotBlank(String str) {
|
||
return str != null && !str.isEmpty() && !str.isBlank();
|
||
}
|
||
|
||
/**
|
||
* 是否不为空白
|
||
*
|
||
* @param str 字符串
|
||
* @param fromIndex 起始位置
|
||
* @param toIndex 结束位置
|
||
* @return 是否为空白
|
||
*/
|
||
public static boolean isNotBlank(String str, int fromIndex, int toIndex) {
|
||
if (str == null || str.isEmpty()) {
|
||
return false;
|
||
}
|
||
for (int i = fromIndex; i < toIndex; i++) {
|
||
char ch = str.charAt(i);
|
||
if (ch != ' ' && ch != '\t' && !Character.isWhitespace(ch)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 是否为空
|
||
*
|
||
* @param str 字符串
|
||
* @return 是否为空
|
||
*/
|
||
public static boolean isEmpty(CharSequence str) {
|
||
return str == null || str.length() == 0;
|
||
}
|
||
|
||
/**
|
||
* 字符串是否至少一个为空
|
||
*
|
||
* @param strs 字符串集合
|
||
* @return 是否为空
|
||
*/
|
||
public static boolean isAnyEmpty(CharSequence... strs) {
|
||
if (strs == null || strs.length == 0) {
|
||
return false;
|
||
}
|
||
for (CharSequence str : strs) {
|
||
if (isEmpty(str)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 是否不为空
|
||
*
|
||
* @param str 字符串
|
||
* @return 是否不为空
|
||
*/
|
||
public static boolean isNotEmpty(CharSequence str) {
|
||
return str != null && str.length() > 0;
|
||
}
|
||
|
||
/**
|
||
* 是否为空
|
||
*
|
||
* @param map Map
|
||
* @return 是否为空
|
||
*/
|
||
public static boolean isEmpty(Map map) {
|
||
return map == null || map.isEmpty();
|
||
}
|
||
|
||
/**
|
||
* 是否不为空
|
||
*
|
||
* @param map Map
|
||
* @return 是否不为空
|
||
*/
|
||
public static boolean isNotEmpty(Map map) {
|
||
return map != null && !map.isEmpty();
|
||
}
|
||
|
||
/**
|
||
* 是否为空
|
||
*
|
||
* @param collection Collection
|
||
* @return 是否为空
|
||
*/
|
||
public static boolean isEmpty(Collection collection) {
|
||
return collection == null || collection.isEmpty();
|
||
}
|
||
|
||
/**
|
||
* 是否不为空
|
||
*
|
||
* @param collection Collection
|
||
* @return 是否不为空
|
||
*/
|
||
public static boolean isNotEmpty(Collection collection) {
|
||
return collection != null && !collection.isEmpty();
|
||
}
|
||
|
||
/**
|
||
* 是否为空
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 数组
|
||
* @return 是否为空
|
||
*/
|
||
public static <T> boolean isEmpty(T[] array) {
|
||
return array == null || array.length == 0;
|
||
}
|
||
|
||
/**
|
||
* 是否不为空
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 数组
|
||
* @return 是否不为空
|
||
*/
|
||
public static <T> boolean isNotEmpty(T[] array) {
|
||
return array != null && array.length > 0;
|
||
}
|
||
|
||
/**
|
||
* 是否为空
|
||
*
|
||
* @param array 数组
|
||
* @return 是否为空
|
||
*/
|
||
public static boolean isEmpty(byte[] array) {
|
||
return array == null || array.length == 0;
|
||
}
|
||
|
||
/**
|
||
* 是否不为空
|
||
*
|
||
* @param array 数组
|
||
* @return 是否不为空
|
||
*/
|
||
public static boolean isNotEmpty(byte[] array) {
|
||
return array != null && array.length > 0;
|
||
}
|
||
|
||
/**
|
||
* 是否为空
|
||
*
|
||
* @param array 数组
|
||
* @return 是否为空
|
||
*/
|
||
public static boolean isEmpty(short[] array) {
|
||
return array == null || array.length == 0;
|
||
}
|
||
|
||
/**
|
||
* 是否不为空
|
||
*
|
||
* @param array 数组
|
||
* @return 是否不为空
|
||
*/
|
||
public static boolean isNotEmpty(short[] array) {
|
||
return array != null && array.length > 0;
|
||
}
|
||
|
||
/**
|
||
* 是否为空
|
||
*
|
||
* @param array 数组
|
||
* @return 是否为空
|
||
*/
|
||
public static boolean isEmpty(int[] array) {
|
||
return array == null || array.length == 0;
|
||
}
|
||
|
||
/**
|
||
* 是否不为空
|
||
*
|
||
* @param array 数组
|
||
* @return 是否不为空
|
||
*/
|
||
public static boolean isNotEmpty(int[] array) {
|
||
return array != null && array.length > 0;
|
||
}
|
||
|
||
/**
|
||
* 是否为空
|
||
*
|
||
* @param array 数组
|
||
* @return 是否为空
|
||
*/
|
||
public static boolean isEmpty(long[] array) {
|
||
return array == null || array.length == 0;
|
||
}
|
||
|
||
/**
|
||
* 是否不为空
|
||
*
|
||
* @param array 数组
|
||
* @return 是否不为空
|
||
*/
|
||
public static boolean isNotEmpty(long[] array) {
|
||
return array != null && array.length > 0;
|
||
}
|
||
|
||
/**
|
||
* 是否为空
|
||
*
|
||
* @param array ByteArray
|
||
* @return 是否为空
|
||
*/
|
||
public static boolean isEmpty(ByteArray array) {
|
||
return array == null || array.isEmpty();
|
||
}
|
||
|
||
/**
|
||
* 是否不为空
|
||
*
|
||
* @param array ByteArray
|
||
* @return 是否不为空
|
||
*/
|
||
public static boolean isNotEmpty(ByteArray array) {
|
||
return array != null && !array.isEmpty();
|
||
}
|
||
|
||
/**
|
||
* 将字符串首字母大写
|
||
*
|
||
* @param str 字符串
|
||
* @return 首字母大写
|
||
*/
|
||
public static String firstCharUpperCase(String str) {
|
||
if (str == null || str.isEmpty()) {
|
||
return str;
|
||
}
|
||
if (Character.isUpperCase(str.charAt(0))) {
|
||
return str;
|
||
}
|
||
char[] chs = str.toCharArray();
|
||
chs[0] = Character.toUpperCase(chs[0]);
|
||
return new String(chs);
|
||
}
|
||
|
||
/**
|
||
* 将字符串首字母小写
|
||
*
|
||
* @param str 字符串
|
||
* @return 首字母小写
|
||
*/
|
||
public static String firstCharLowerCase(String str) {
|
||
if (str == null || str.isEmpty()) {
|
||
return str;
|
||
}
|
||
if (Character.isLowerCase(str.charAt(0))) {
|
||
return str;
|
||
}
|
||
char[] chs = str.toCharArray();
|
||
chs[0] = Character.toLowerCase(chs[0]);
|
||
return new String(chs);
|
||
}
|
||
|
||
public static boolean[] box(Boolean[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
boolean[] rs = new boolean[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i] != null && array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static Boolean[] box(boolean[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
Boolean[] rs = new Boolean[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static byte[] box(Byte[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
byte[] rs = new byte[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i] == null ? 0 : array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static Byte[] box(byte[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
Byte[] rs = new Byte[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static char[] box(Character[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
char[] rs = new char[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i] == null ? 0 : array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static Character[] box(char[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
Character[] rs = new Character[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static short[] box(Short[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
short[] rs = new short[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i] == null ? 0 : array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static Short[] box(short[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
Short[] rs = new Short[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static int[] box(Integer[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
int[] rs = new int[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i] == null ? 0 : array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static Integer[] box(int[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
Integer[] rs = new Integer[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static long[] box(Long[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
long[] rs = new long[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i] == null ? 0 : array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static Long[] box(long[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
Long[] rs = new Long[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static float[] box(Float[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
float[] rs = new float[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i] == null ? 0 : array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static Float[] box(float[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
Float[] rs = new Float[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static double[] box(Double[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
double[] rs = new double[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i] == null ? 0 : array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static Double[] box(double[] array) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
Double[] rs = new Double[array.length];
|
||
for (int i = 0; i < rs.length; i++) {
|
||
rs[i] = array[i];
|
||
}
|
||
return rs;
|
||
}
|
||
|
||
public static <T> boolean[] reverse(boolean[] array) {
|
||
if (array == null) {
|
||
return array;
|
||
}
|
||
boolean[] arr = array;
|
||
int start = 0;
|
||
int end = arr.length - 1;
|
||
while (start < end) {
|
||
boolean temp = arr[start];
|
||
arr[start] = arr[end];
|
||
arr[end] = temp;
|
||
start++;
|
||
end--;
|
||
}
|
||
return arr;
|
||
}
|
||
|
||
public static <T> byte[] reverse(byte[] array) {
|
||
if (array == null) {
|
||
return array;
|
||
}
|
||
byte[] arr = array;
|
||
int start = 0;
|
||
int end = arr.length - 1;
|
||
while (start < end) {
|
||
byte temp = arr[start];
|
||
arr[start] = arr[end];
|
||
arr[end] = temp;
|
||
start++;
|
||
end--;
|
||
}
|
||
return arr;
|
||
}
|
||
|
||
public static <T> char[] reverse(char[] array) {
|
||
if (array == null) {
|
||
return array;
|
||
}
|
||
char[] arr = array;
|
||
int start = 0;
|
||
int end = arr.length - 1;
|
||
while (start < end) {
|
||
char temp = arr[start];
|
||
arr[start] = arr[end];
|
||
arr[end] = temp;
|
||
start++;
|
||
end--;
|
||
}
|
||
return arr;
|
||
}
|
||
|
||
public static <T> short[] reverse(short[] array) {
|
||
if (array == null) {
|
||
return array;
|
||
}
|
||
short[] arr = array;
|
||
int start = 0;
|
||
int end = arr.length - 1;
|
||
while (start < end) {
|
||
short temp = arr[start];
|
||
arr[start] = arr[end];
|
||
arr[end] = temp;
|
||
start++;
|
||
end--;
|
||
}
|
||
return arr;
|
||
}
|
||
|
||
public static <T> int[] reverse(int[] array) {
|
||
if (array == null) {
|
||
return array;
|
||
}
|
||
int[] arr = array;
|
||
int start = 0;
|
||
int end = arr.length - 1;
|
||
while (start < end) {
|
||
int temp = arr[start];
|
||
arr[start] = arr[end];
|
||
arr[end] = temp;
|
||
start++;
|
||
end--;
|
||
}
|
||
return arr;
|
||
}
|
||
|
||
public static <T> long[] reverse(long[] array) {
|
||
if (array == null) {
|
||
return array;
|
||
}
|
||
long[] arr = array;
|
||
int start = 0;
|
||
int end = arr.length - 1;
|
||
while (start < end) {
|
||
long temp = arr[start];
|
||
arr[start] = arr[end];
|
||
arr[end] = temp;
|
||
start++;
|
||
end--;
|
||
}
|
||
return arr;
|
||
}
|
||
|
||
public static <T> float[] reverse(float[] array) {
|
||
if (array == null) {
|
||
return array;
|
||
}
|
||
float[] arr = array;
|
||
int start = 0;
|
||
int end = arr.length - 1;
|
||
while (start < end) {
|
||
float temp = arr[start];
|
||
arr[start] = arr[end];
|
||
arr[end] = temp;
|
||
start++;
|
||
end--;
|
||
}
|
||
return arr;
|
||
}
|
||
|
||
public static <T> double[] reverse(double[] array) {
|
||
if (array == null) {
|
||
return array;
|
||
}
|
||
double[] arr = array;
|
||
int start = 0;
|
||
int end = arr.length - 1;
|
||
while (start < end) {
|
||
double temp = arr[start];
|
||
arr[start] = arr[end];
|
||
arr[end] = temp;
|
||
start++;
|
||
end--;
|
||
}
|
||
return arr;
|
||
}
|
||
|
||
public static <T> T[] reverse(T[] array) {
|
||
if (array == null) {
|
||
return array;
|
||
}
|
||
T[] arr = array;
|
||
int start = 0;
|
||
int end = arr.length - 1;
|
||
while (start < end) {
|
||
T temp = arr[start];
|
||
arr[start] = arr[end];
|
||
arr[end] = temp;
|
||
start++;
|
||
end--;
|
||
}
|
||
return arr;
|
||
}
|
||
|
||
public static <T> List<T> reverse(List<T> list) {
|
||
if (list != null) {
|
||
Collections.reverse(list);
|
||
}
|
||
return list;
|
||
}
|
||
|
||
/**
|
||
* 将多个key:value对应值组合成一个Map,items长度必须是偶数, 参数个数若是奇数的话,最后一个会被忽略 类似 JDK9中的 Map.of 方法
|
||
*
|
||
* @param <K> 泛型
|
||
* @param <V> 泛型
|
||
* @param items 键值对
|
||
* @return Map
|
||
*/
|
||
@ClassDepends
|
||
public static <K, V> HashMap<K, V> ofMap(Object... items) {
|
||
HashMap<K, V> map = new LinkedHashMap<>(Math.max(1, items.length / 2));
|
||
int len = items.length / 2;
|
||
for (int i = 0; i < len; i++) {
|
||
map.put((K) items[i * 2], (V) items[i * 2 + 1]);
|
||
}
|
||
return map;
|
||
}
|
||
|
||
/**
|
||
* 将多个Map合并到第一个Map中
|
||
*
|
||
* @param <K> 泛型
|
||
* @param <V> 泛型
|
||
* @param maps Map
|
||
* @return Map
|
||
*/
|
||
public static <K, V> Map<K, V> merge(Map<K, V>... maps) {
|
||
Map<K, V> map = null;
|
||
for (Map<K, V> m : maps) {
|
||
if (map == null) {
|
||
map = m;
|
||
} else if (m != null) {
|
||
map.putAll(m);
|
||
}
|
||
}
|
||
return map;
|
||
}
|
||
|
||
/**
|
||
* 将多个元素组合成一个Set
|
||
*
|
||
* @param <T> 泛型
|
||
* @param items 元素
|
||
* @return Set
|
||
*/
|
||
public static <T> Set<T> ofSet(T... items) {
|
||
Set<T> set = new LinkedHashSet<>(items.length);
|
||
for (T item : items) set.add(item);
|
||
return set;
|
||
}
|
||
|
||
/**
|
||
* 将多个元素组合成一个List <br>
|
||
* 类似 JDK9中的 List.of 方法
|
||
*
|
||
* @param <T> 泛型
|
||
* @param items 元素
|
||
* @return List
|
||
*/
|
||
public static <T> List<T> ofList(T... items) {
|
||
List<T> list = new ArrayList<>(items.length);
|
||
for (T item : items) list.add(item);
|
||
return list;
|
||
}
|
||
|
||
/**
|
||
* 将多个元素组合成一个Array
|
||
*
|
||
* @param <T> 泛型
|
||
* @param items 元素
|
||
* @return Array
|
||
*/
|
||
public static <T> T[] ofArray(T... items) {
|
||
return items;
|
||
}
|
||
|
||
/**
|
||
* 裁剪List,使其size不超过limit大小 <br>
|
||
*
|
||
* @param <T> 泛型
|
||
* @param list 集合
|
||
* @param limit 大小
|
||
* @return List
|
||
*/
|
||
public static <T> List<T> limit(List<T> list, int limit) {
|
||
if (list == null || list.isEmpty() || list.size() <= limit) {
|
||
return list;
|
||
}
|
||
return list.subList(0, limit);
|
||
}
|
||
|
||
/**
|
||
* 获取不带"-"的UUID值
|
||
*
|
||
* @return 不带"-"UUID值
|
||
*/
|
||
public static String uuid() {
|
||
return UUID.randomUUID().toString().replace("-", "");
|
||
}
|
||
|
||
/**
|
||
* 比较两个版本号的大小,ver1小于ver2返回 -1
|
||
*
|
||
* @param version1 版本号
|
||
* @param version2 版本号
|
||
* @return 版本大小
|
||
*/
|
||
public static int compareVersion(String version1, String version2) {
|
||
if (isEmpty(version1)) {
|
||
return isEmpty(version2) ? 0 : -1;
|
||
}
|
||
if (isEmpty(version2)) {
|
||
return 1;
|
||
}
|
||
String[] ver1 = version1.split("\\.");
|
||
String[] ver2 = version2.split("\\.");
|
||
int len = Math.min(ver1.length, ver2.length);
|
||
for (int i = 0; i < len; i++) {
|
||
if (ver1[i].length() > ver2[i].length()) {
|
||
return 1;
|
||
}
|
||
if (ver1[i].length() < ver2[i].length()) {
|
||
return -1;
|
||
}
|
||
int v = Integer.parseInt(ver1[i]) - Integer.parseInt(ver2[i]);
|
||
if (v != 0) {
|
||
return v > 0 ? 1 : -1;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* 排序, 值大排前面
|
||
* @param <P> 泛型
|
||
* @param list 集合
|
||
* @return 排序后的集合
|
||
*/
|
||
public static <P> List<P> sortPriority(List<P> list) {
|
||
Collections.sort(list, (a, b) -> {
|
||
Priority p1 = a == null ? null : a.getClass().getAnnotation(Priority.class);
|
||
Priority p2 = b == null ? null : b.getClass().getAnnotation(Priority.class);
|
||
return (p2 == null ? 0 : p2.value()) - (p1 == null ? 0 : p1.value());
|
||
});
|
||
return list;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个新元素添加到数组开始,数组中的元素自动后移
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static <T> T[] unshift(final T[] array, final T... objs) {
|
||
if (array == null || array.length == 0) {
|
||
return objs;
|
||
}
|
||
final T[] news = (T[]) Creator.newArray(array.getClass().getComponentType(), array.length + objs.length);
|
||
System.arraycopy(objs, 0, news, 0, objs.length);
|
||
System.arraycopy(array, 0, news, objs.length, array.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个新元素添加到数组开始,数组中的元素自动后移
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static <T> T[] unshift(final T[] array, final Collection<T> objs) {
|
||
if (objs == null || objs.isEmpty()) {
|
||
return array;
|
||
}
|
||
if (array == null) {
|
||
T one = null;
|
||
for (T t : objs) {
|
||
if (t != null) {
|
||
one = t;
|
||
}
|
||
break;
|
||
}
|
||
if (one == null) {
|
||
return array;
|
||
}
|
||
T[] news = (T[]) Creator.newArray(one.getClass(), objs.size());
|
||
return objs.toArray(news);
|
||
}
|
||
T[] news = (T[]) Creator.newArray(array.getClass().getComponentType(), array.length + objs.size());
|
||
int index = -1;
|
||
for (T t : objs) {
|
||
news[(++index)] = t;
|
||
}
|
||
System.arraycopy(array, 0, news, objs.size(), array.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 获取int数组之和, 空数组返回0
|
||
*
|
||
* @param array 数组
|
||
* @return int
|
||
*/
|
||
public static int sum(final int... array) {
|
||
return sum(false, array);
|
||
}
|
||
|
||
/**
|
||
* 获取int数组之和
|
||
*
|
||
* @param check 是否检测空
|
||
* @param array 数组
|
||
* @return int
|
||
*/
|
||
public static int sum(boolean check, final int... array) {
|
||
if (array == null || array.length == 0) {
|
||
if (!check) {
|
||
return 0;
|
||
}
|
||
throw new NullPointerException("array is null or empty");
|
||
}
|
||
int sum = 0;
|
||
for (int i : array) {
|
||
sum += i;
|
||
}
|
||
return sum;
|
||
}
|
||
|
||
/**
|
||
* 获取long数组之和, 空数组返回0
|
||
*
|
||
* @param array 数组
|
||
* @return long
|
||
*/
|
||
public static long sum(final long... array) {
|
||
return sum(false, array);
|
||
}
|
||
|
||
/**
|
||
* 获取long数组之和
|
||
*
|
||
* @param check 是否检测空
|
||
* @param array 数组
|
||
* @return long
|
||
*/
|
||
public static long sum(boolean check, final long... array) {
|
||
if (array == null || array.length == 0) {
|
||
if (!check) {
|
||
return 0;
|
||
}
|
||
throw new NullPointerException("array is null or empty");
|
||
}
|
||
long sum = 0L;
|
||
for (long i : array) {
|
||
sum += i;
|
||
}
|
||
return sum;
|
||
}
|
||
|
||
/**
|
||
* 获取int数组最大值
|
||
*
|
||
* @param array 数组
|
||
* @return int
|
||
*/
|
||
public static int max(final int... array) {
|
||
if (array == null || array.length == 0) {
|
||
throw new NullPointerException("array is null or empty");
|
||
}
|
||
int max = array[0];
|
||
for (int i : array) {
|
||
if (i > max) {
|
||
i = max;
|
||
}
|
||
}
|
||
return max;
|
||
}
|
||
|
||
/**
|
||
* 获取long数组最大值
|
||
*
|
||
* @param array 数组
|
||
* @return long
|
||
*/
|
||
public static long max(final long... array) {
|
||
if (array == null || array.length == 0) {
|
||
throw new NullPointerException("array is null or empty");
|
||
}
|
||
long max = array[0];
|
||
for (long i : array) {
|
||
if (i > max) {
|
||
i = max;
|
||
}
|
||
}
|
||
return max;
|
||
}
|
||
|
||
/**
|
||
* 获取int数组最小值
|
||
*
|
||
* @param array 数组
|
||
* @return int
|
||
*/
|
||
public static long min(final int... array) {
|
||
if (array == null || array.length == 0) {
|
||
throw new NullPointerException("array is null or empty");
|
||
}
|
||
int min = array[0];
|
||
for (int i : array) {
|
||
if (i < min) {
|
||
i = min;
|
||
}
|
||
}
|
||
return min;
|
||
}
|
||
|
||
/**
|
||
* 获取long数组最小值
|
||
*
|
||
* @param array 数组
|
||
* @return long
|
||
*/
|
||
public static long min(final long... array) {
|
||
if (array == null || array.length == 0) {
|
||
throw new NullPointerException("array is null or empty");
|
||
}
|
||
long min = array[0];
|
||
for (long i : array) {
|
||
if (i < min) {
|
||
i = min;
|
||
}
|
||
}
|
||
return min;
|
||
}
|
||
|
||
/**
|
||
* 将char数组用分隔符拼接成字符串
|
||
*
|
||
* @param array 数组
|
||
* @param delimiter 分隔符
|
||
* @return String
|
||
*/
|
||
public static String joining(final char[] array, final String delimiter) {
|
||
if (array == null || array.length == 0) {
|
||
return "";
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
for (char i : array) {
|
||
if (sb.length() > 0) {
|
||
sb.append(delimiter);
|
||
}
|
||
sb.append(i);
|
||
}
|
||
return sb.toString();
|
||
}
|
||
|
||
/**
|
||
* 将int数组用分隔符拼接成字符串
|
||
*
|
||
* @param array 数组
|
||
* @param delimiter 分隔符
|
||
* @return String
|
||
*/
|
||
public static String joining(final int[] array, final String delimiter) {
|
||
if (array == null || array.length == 0) {
|
||
return "";
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
for (int i : array) {
|
||
if (sb.length() > 0) {
|
||
sb.append(delimiter);
|
||
}
|
||
sb.append(i);
|
||
}
|
||
return sb.toString();
|
||
}
|
||
|
||
/**
|
||
* 将long数组用分隔符拼接成字符串
|
||
*
|
||
* @param array 数组
|
||
* @param delimiter 分隔符
|
||
* @return String
|
||
*/
|
||
public static String joining(final long[] array, final String delimiter) {
|
||
if (array == null || array.length == 0) {
|
||
return "";
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
for (long i : array) {
|
||
if (sb.length() > 0) {
|
||
sb.append(delimiter);
|
||
}
|
||
sb.append(i);
|
||
}
|
||
return sb.toString();
|
||
}
|
||
|
||
/**
|
||
* 将对象数组用分隔符拼接成字符串
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 数组
|
||
* @param delimiter 分隔符
|
||
* @return String
|
||
*/
|
||
public static <T> String joining(final T[] array, final String delimiter) {
|
||
if (array == null || array.length == 0) {
|
||
return "";
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
for (T i : array) {
|
||
if (sb.length() > 0) {
|
||
sb.append(delimiter);
|
||
}
|
||
sb.append(i);
|
||
}
|
||
return sb.toString();
|
||
}
|
||
|
||
/**
|
||
* 将对象集合用分隔符拼接成字符串
|
||
*
|
||
* @param <T> 泛型
|
||
* @param stream 集合
|
||
* @param delimiter 分隔符
|
||
* @return String
|
||
*/
|
||
public static <T> String joining(final Stream<T> stream, final String delimiter) {
|
||
if (stream == null) {
|
||
return "";
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
stream.forEach(i -> {
|
||
if (sb.length() > 0) {
|
||
sb.append(delimiter);
|
||
}
|
||
sb.append(i);
|
||
});
|
||
return sb.toString();
|
||
}
|
||
|
||
/**
|
||
* 将对象数组用分隔符拼接成字符串
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 数组
|
||
* @param delimiter 分隔符
|
||
* @return String
|
||
*/
|
||
public static <T> String joining(final String[] array, final char delimiter) {
|
||
if (array == null || array.length == 0) {
|
||
return "";
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
for (String i : array) {
|
||
if (sb.length() > 0) {
|
||
sb.append(delimiter);
|
||
}
|
||
sb.append(i);
|
||
}
|
||
return sb.toString();
|
||
}
|
||
|
||
/**
|
||
* 将对象数组用分隔符拼接成字符串
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 数组
|
||
* @param delimiter 分隔符
|
||
* @return String
|
||
*/
|
||
public static <T> String joiningHex(final byte[] array, final char delimiter) {
|
||
if (array == null || array.length == 0) {
|
||
return "";
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
for (byte i : array) {
|
||
if (sb.length() > 0) {
|
||
sb.append(delimiter);
|
||
}
|
||
String s = Integer.toHexString(i & 0xff);
|
||
sb.append(s.length() > 1 ? "0x" : "0x0").append(s);
|
||
}
|
||
return sb.toString();
|
||
}
|
||
|
||
/**
|
||
* 将对象数组用分隔符拼接成字符串
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 数组
|
||
* @param offset 偏移量
|
||
* @param length 长度
|
||
* @param delimiter 分隔符
|
||
* @return String
|
||
*/
|
||
public static <T> String joiningHex(final byte[] array, int offset, int length, final char delimiter) {
|
||
if (array == null || array.length == 0) {
|
||
return "";
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
int len = offset + length;
|
||
for (int i = offset; i < len; i++) {
|
||
if (sb.length() > 0) {
|
||
sb.append(delimiter);
|
||
}
|
||
String s = Integer.toHexString(array[i] & 0xff);
|
||
sb.append(s.length() > 1 ? "0x" : "0x0").append(s);
|
||
}
|
||
return sb.toString();
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个byte新元素添加到byte数组结尾
|
||
*
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static byte[] append(final byte[] array, final byte... objs) {
|
||
if (array == null || array.length == 0) {
|
||
return objs;
|
||
}
|
||
if (objs == null || objs.length == 0) {
|
||
return array;
|
||
}
|
||
final byte[] news = new byte[array.length + objs.length];
|
||
System.arraycopy(array, 0, news, 0, array.length);
|
||
System.arraycopy(objs, 0, news, array.length, objs.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个byte新元素添加到byte数组结尾
|
||
*
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @param offset 待追加数据偏移量
|
||
* @param length 待追加数据的长度
|
||
* @return 新数组
|
||
*/
|
||
public static byte[] append(final byte[] array, final byte[] objs, int offset, int length) {
|
||
if (array == null || array.length == 0) {
|
||
if (objs != null && offset == 0 && objs.length == length) {
|
||
return objs;
|
||
}
|
||
final byte[] news = new byte[length];
|
||
System.arraycopy(objs, 0, news, 0, length);
|
||
return news;
|
||
}
|
||
if (objs == null || length == 0) {
|
||
return array;
|
||
}
|
||
final byte[] news = new byte[array.length + length];
|
||
System.arraycopy(array, 0, news, 0, array.length);
|
||
System.arraycopy(objs, offset, news, array.length, length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个short新元素添加到short数组结尾
|
||
*
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static short[] append(final short[] array, final short... objs) {
|
||
if (array == null || array.length == 0) {
|
||
return objs;
|
||
}
|
||
if (objs == null || objs.length == 0) {
|
||
return array;
|
||
}
|
||
final short[] news = new short[array.length + objs.length];
|
||
System.arraycopy(array, 0, news, 0, array.length);
|
||
System.arraycopy(objs, 0, news, array.length, objs.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个char新元素添加到char数组结尾
|
||
*
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static char[] append(final char[] array, final char... objs) {
|
||
if (array == null || array.length == 0) {
|
||
return objs;
|
||
}
|
||
if (objs == null || objs.length == 0) {
|
||
return array;
|
||
}
|
||
final char[] news = new char[array.length + objs.length];
|
||
System.arraycopy(array, 0, news, 0, array.length);
|
||
System.arraycopy(objs, 0, news, array.length, objs.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个int新元素添加到int数组结尾
|
||
*
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static int[] append(final int[] array, final int... objs) {
|
||
if (array == null || array.length == 0) {
|
||
return objs;
|
||
}
|
||
if (objs == null || objs.length == 0) {
|
||
return array;
|
||
}
|
||
final int[] news = new int[array.length + objs.length];
|
||
System.arraycopy(array, 0, news, 0, array.length);
|
||
System.arraycopy(objs, 0, news, array.length, objs.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个long新元素添加到long数组结尾
|
||
*
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static long[] append(final long[] array, final long... objs) {
|
||
if (array == null || array.length == 0) {
|
||
return objs;
|
||
}
|
||
if (objs == null || objs.length == 0) {
|
||
return array;
|
||
}
|
||
final long[] news = new long[array.length + objs.length];
|
||
System.arraycopy(array, 0, news, 0, array.length);
|
||
System.arraycopy(objs, 0, news, array.length, objs.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个新元素添加到数组结尾
|
||
*
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static String[] append(final String[] array, final String... objs) {
|
||
if (array == null || array.length == 0) {
|
||
return objs;
|
||
}
|
||
if (objs == null || objs.length == 0) {
|
||
return array;
|
||
}
|
||
final String[] news = new String[array.length + objs.length];
|
||
System.arraycopy(array, 0, news, 0, array.length);
|
||
System.arraycopy(objs, 0, news, array.length, objs.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个新元素添加到数组结尾
|
||
*
|
||
* @param one 单个对象
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static String[] append(final String one, final String... objs) {
|
||
if (one == null) {
|
||
return objs;
|
||
}
|
||
final String[] news = new String[1 + objs.length];
|
||
news[0] = one;
|
||
System.arraycopy(objs, 0, news, 1, objs.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个新元素添加到数组结尾
|
||
*
|
||
* @param one 单个对象
|
||
* @param two 单个对象
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static String[] append(final String one, String two, final String... objs) {
|
||
final String[] news = new String[2 + objs.length];
|
||
news[0] = one;
|
||
news[1] = two;
|
||
System.arraycopy(objs, 0, news, 2, objs.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个新元素添加到数组结尾
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static <T> T[] append(final T[] array, final T... objs) {
|
||
if (array == null || array.length == 0) {
|
||
return objs;
|
||
}
|
||
if (objs == null || objs.length == 0) {
|
||
return array;
|
||
}
|
||
final T[] news = (T[]) Creator.newArray(array.getClass().getComponentType(), array.length + objs.length);
|
||
System.arraycopy(array, 0, news, 0, array.length);
|
||
System.arraycopy(objs, 0, news, array.length, objs.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个新元素添加到数组结尾
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static <T> Object[][] append(final Object[][] array, final Object[]... objs) {
|
||
if (array == null || array.length == 0) {
|
||
return objs;
|
||
}
|
||
if (objs == null || objs.length == 0) {
|
||
return array;
|
||
}
|
||
final Object[][] news = new Object[array.length + objs.length][];
|
||
System.arraycopy(array, 0, news, 0, array.length);
|
||
System.arraycopy(objs, 0, news, array.length, objs.length);
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将一个或多个新元素添加到数组结尾
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 原数组
|
||
* @param objs 待追加数据
|
||
* @return 新数组
|
||
*/
|
||
public static <T> T[] append(final T[] array, final Collection<T> objs) {
|
||
if (objs == null || objs.isEmpty()) {
|
||
return array;
|
||
}
|
||
if (array == null) {
|
||
T one = null;
|
||
for (T t : objs) {
|
||
if (t != null) {
|
||
one = t;
|
||
}
|
||
break;
|
||
}
|
||
if (one == null) {
|
||
return array;
|
||
}
|
||
T[] news = (T[]) Creator.newArray(one.getClass(), objs.size());
|
||
return objs.toArray(news);
|
||
}
|
||
T[] news = (T[]) Creator.newArray(array.getClass().getComponentType(), array.length + objs.size());
|
||
System.arraycopy(array, 0, news, 0, array.length);
|
||
int index = -1;
|
||
for (T t : objs) {
|
||
news[array.length + (++index)] = t;
|
||
}
|
||
return news;
|
||
}
|
||
|
||
/**
|
||
* 将元素从数组中删除
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 原数组
|
||
* @param item 元素
|
||
* @return 新数组
|
||
*/
|
||
public static <T> T[] remove(final T[] array, final T item) {
|
||
return remove(array, (i) -> Objects.equals(i, item));
|
||
}
|
||
|
||
/**
|
||
* 将符合条件的元素从数组中删除
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 原数组
|
||
* @param filter Predicate
|
||
* @return 新数组
|
||
*/
|
||
public static <T> T[] remove(final T[] array, final Predicate filter) {
|
||
if (array == null || array.length == 0 || filter == null) {
|
||
return array;
|
||
}
|
||
final T[] news = (T[]) Creator.newArray(array.getClass().getComponentType(), array.length);
|
||
int index = 0;
|
||
for (int i = 0; i < news.length; i++) {
|
||
if (!filter.test(array[i])) {
|
||
news[index++] = array[i];
|
||
}
|
||
}
|
||
if (index == array.length) {
|
||
return array;
|
||
}
|
||
final T[] rs = (T[]) Creator.newArray(array.getClass().getComponentType(), index);
|
||
System.arraycopy(news, 0, rs, 0, index);
|
||
return rs;
|
||
}
|
||
|
||
/**
|
||
* 将符合条件的元素从数组中删除
|
||
*
|
||
* @param array 原数组
|
||
* @param item 元素
|
||
* @return 新数组
|
||
*/
|
||
public static String[] remove(final String[] array, final String item) {
|
||
if (array == null || array.length == 0) {
|
||
return array;
|
||
}
|
||
final String[] news = new String[array.length];
|
||
int index = 0;
|
||
for (int i = 0; i < news.length; i++) {
|
||
if (item != null && !item.equals(array[i])) {
|
||
news[index++] = array[i];
|
||
} else if (item == null && array[i] != null) {
|
||
news[index++] = array[i];
|
||
}
|
||
}
|
||
if (index == array.length) {
|
||
return array;
|
||
}
|
||
final String[] rs = new String[index];
|
||
System.arraycopy(news, 0, rs, 0, index);
|
||
return rs;
|
||
}
|
||
|
||
/**
|
||
* 将指定的long元素从数组中删除, 相同的元素会根据items里重复次数来执行删除 <br>
|
||
* 例如: <br>
|
||
* remove(new short[]{1, 1, 1, 2, 2, 3, 3, 3}, false, 1, 1, 2, 3, 3) = [1,2,3]<br>
|
||
*
|
||
* @param array 原数组
|
||
* @param items short[]
|
||
* @return 新数组
|
||
*/
|
||
public static short[] removeMatch(final short[] array, final short... items) {
|
||
return remove(array, false, items);
|
||
}
|
||
|
||
/**
|
||
* 将指定的int元素从数组中删除, repeat=true时相同的元素会根据items里重复次数来执行删除 <br>
|
||
* 例如: <br>
|
||
* remove(new short[]{1, 1, 1, 2, 2, 3, 3, 3}, true, 1, 1, 2, 3, 3) = [] <br>
|
||
* remove(new short[]{1, 1, 1, 2, 2, 3, 3, 3}, false, 1, 1, 2, 3, 3) = [1,2,3]
|
||
*
|
||
* @param array 原数组
|
||
* @param repeat 是否重复删除相同的元素
|
||
* @param items short[]
|
||
* @return 新数组
|
||
*/
|
||
public static short[] remove(final short[] array, boolean repeat, final short... items) {
|
||
if (array == null || array.length == 0 || items == null || items.length == 0) {
|
||
return array;
|
||
}
|
||
final short[] news = new short[array.length];
|
||
short[] subs = items;
|
||
int index = 0;
|
||
for (int i = 0; i < news.length; i++) {
|
||
if (subs.length > 0 && contains(subs, array[i])) {
|
||
if (!repeat) {
|
||
short[] newsubs = new short[subs.length - 1];
|
||
int k = 0;
|
||
boolean done = false;
|
||
for (short v : subs) {
|
||
if (done) {
|
||
newsubs[k++] = v;
|
||
} else if (v == array[i]) {
|
||
done = true;
|
||
} else {
|
||
newsubs[k++] = v;
|
||
}
|
||
}
|
||
subs = newsubs;
|
||
}
|
||
} else {
|
||
news[index++] = array[i];
|
||
}
|
||
}
|
||
if (index == array.length) {
|
||
return array;
|
||
}
|
||
final short[] rs = new short[index];
|
||
System.arraycopy(news, 0, rs, 0, index);
|
||
return rs;
|
||
}
|
||
|
||
/**
|
||
* 将指定的long元素从数组中删除, 相同的元素会根据items里重复次数来执行删除 <br>
|
||
* 例如: <br>
|
||
* remove(new int[]{1, 1, 1, 2, 2, 3, 3, 3}, false, 1, 1, 2, 3, 3) = [1,2,3]<br>
|
||
*
|
||
* @param array 原数组
|
||
* @param items int[]
|
||
* @return 新数组
|
||
*/
|
||
public static int[] removeMatch(final int[] array, final int... items) {
|
||
return remove(array, false, items);
|
||
}
|
||
|
||
/**
|
||
* 将指定的int元素从数组中删除, repeat=false时相同的元素会根据items里重复次数来执行删除 <br>
|
||
* 例如: <br>
|
||
* remove(new int[]{1, 1, 1, 2, 2, 3, 3, 3}, true, 1, 1, 2, 3, 3) = [] <br>
|
||
* remove(new int[]{1, 1, 1, 2, 2, 3, 3, 3}, false, 1, 1, 2, 3, 3) = [1,2,3]
|
||
*
|
||
* @param array 原数组
|
||
* @param repeat 是否重复删除相同的元素
|
||
* @param items int[]
|
||
* @return 新数组
|
||
*/
|
||
public static int[] remove(final int[] array, boolean repeat, final int... items) {
|
||
if (array == null || array.length == 0 || items == null || items.length == 0) {
|
||
return array;
|
||
}
|
||
final int[] news = new int[array.length];
|
||
int[] subs = items;
|
||
int index = 0;
|
||
for (int i = 0; i < news.length; i++) {
|
||
if (subs.length > 0 && contains(subs, array[i])) {
|
||
if (!repeat) {
|
||
int[] newsubs = new int[subs.length - 1];
|
||
int k = 0;
|
||
boolean done = false;
|
||
for (int v : subs) {
|
||
if (done) {
|
||
newsubs[k++] = v;
|
||
} else if (v == array[i]) {
|
||
done = true;
|
||
} else {
|
||
newsubs[k++] = v;
|
||
}
|
||
}
|
||
subs = newsubs;
|
||
}
|
||
} else {
|
||
news[index++] = array[i];
|
||
}
|
||
}
|
||
if (index == array.length) {
|
||
return array;
|
||
}
|
||
final int[] rs = new int[index];
|
||
System.arraycopy(news, 0, rs, 0, index);
|
||
return rs;
|
||
}
|
||
|
||
/**
|
||
* 将指定的long元素从数组中删除, 相同的元素会根据items里重复次数来执行删除 <br>
|
||
* 例如: <br>
|
||
* remove(new long[]{1, 1, 1, 2, 2, 3, 3, 3}, false, 1, 1, 2, 3, 3) = [1,2,3]<br>
|
||
*
|
||
* @param array 原数组
|
||
* @param items long[]
|
||
* @return 新数组
|
||
*/
|
||
public static long[] removeMatch(final long[] array, final long... items) {
|
||
return remove(array, false, items);
|
||
}
|
||
|
||
/**
|
||
* 将指定的long元素从数组中删除, repeat=false时相同的元素会根据items里重复次数来执行删除 <br>
|
||
* 例如: <br>
|
||
* remove(new long[]{1, 1, 1, 2, 2, 3, 3, 3}, true, 1, 1, 2, 3, 3) = [] <br>
|
||
* remove(new long[]{1, 1, 1, 2, 2, 3, 3, 3}, false, 1, 1, 2, 3, 3) = [1,2,3]<br>
|
||
*
|
||
* @param array 原数组
|
||
* @param repeat 是否重复删除相同的元素
|
||
* @param items long[]
|
||
* @return 新数组
|
||
*/
|
||
public static long[] remove(final long[] array, boolean repeat, final long... items) {
|
||
if (array == null || array.length == 0 || items == null || items.length == 0) {
|
||
return array;
|
||
}
|
||
final long[] news = new long[array.length];
|
||
long[] subs = items;
|
||
int index = 0;
|
||
for (int i = 0; i < news.length; i++) {
|
||
if (subs.length > 0 && contains(subs, array[i])) {
|
||
if (!repeat) {
|
||
long[] newsubs = new long[subs.length - 1];
|
||
int k = 0;
|
||
boolean done = false;
|
||
for (long v : subs) {
|
||
if (done) {
|
||
newsubs[k++] = v;
|
||
} else if (v == array[i]) {
|
||
done = true;
|
||
} else {
|
||
newsubs[k++] = v;
|
||
}
|
||
}
|
||
subs = newsubs;
|
||
}
|
||
} else {
|
||
news[index++] = array[i];
|
||
}
|
||
}
|
||
if (index == array.length) {
|
||
return array;
|
||
}
|
||
final long[] rs = new long[index];
|
||
System.arraycopy(news, 0, rs, 0, index);
|
||
return rs;
|
||
}
|
||
|
||
/**
|
||
* 将符合条件的元素从集合中删除
|
||
*
|
||
* @param <T> 泛型
|
||
* @param objs 原集合
|
||
* @param filter Predicate
|
||
* @return 新集合
|
||
*/
|
||
public static <T> Collection<T> remove(final Collection<T> objs, Predicate filter) {
|
||
if (objs == null || filter == null) {
|
||
return objs;
|
||
}
|
||
List<T> list = new ArrayList<>();
|
||
for (T t : objs) {
|
||
if (filter.test(t)) {
|
||
list.add(t);
|
||
}
|
||
}
|
||
if (!list.isEmpty()) {
|
||
objs.removeAll(list);
|
||
}
|
||
return objs;
|
||
}
|
||
|
||
/**
|
||
* 判断字符串是否包含指定的字符,包含返回true
|
||
*
|
||
* @param string 字符串
|
||
* @param values 字符集合
|
||
* @return boolean
|
||
*/
|
||
public static boolean contains(String string, char... values) {
|
||
if (string == null) {
|
||
return false;
|
||
}
|
||
for (char ch : Utility.charArray(string)) {
|
||
for (char ch2 : values) {
|
||
if (ch == ch2) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 比较两集合元素是否一样, 顺序不要求一样
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array1 集合
|
||
* @param array2 集合
|
||
* @return 元素是否完全相同
|
||
*/
|
||
public static <T> boolean equalsElement(T[] array1, T[] array2) {
|
||
if (array1 == null && array2 == null) {
|
||
return true;
|
||
}
|
||
if (array1 == null || array2 == null) {
|
||
return false;
|
||
}
|
||
if (array1.length != array2.length) {
|
||
return false;
|
||
}
|
||
return equalsElement(ofList(array1), ofList(array2));
|
||
}
|
||
|
||
/**
|
||
* 比较两集合元素是否一样, 顺序不要求一样
|
||
*
|
||
* @param <T> 泛型
|
||
* @param col1 集合
|
||
* @param col2 集合
|
||
* @return 元素是否完全相同
|
||
*/
|
||
public static <T> boolean equalsElement(Collection<T> col1, Collection<T> col2) {
|
||
if (col1 == null && col2 == null) {
|
||
return true;
|
||
}
|
||
if (col1 == null || col2 == null) {
|
||
return false;
|
||
}
|
||
if (col1.size() != col2.size()) {
|
||
return false;
|
||
}
|
||
// {1,2,2}, {1,1,2}
|
||
List<T> list = new ArrayList<>(col2);
|
||
for (T item : col1) {
|
||
if (!list.remove(item)) {
|
||
return false;
|
||
}
|
||
}
|
||
return list.isEmpty();
|
||
}
|
||
|
||
/**
|
||
* 比较两集合元素是否一样, 顺序不要求一样
|
||
*
|
||
* @param <K> 泛型
|
||
* @param <V> 泛型
|
||
* @param map1 集合
|
||
* @param map2 集合
|
||
* @return 元素是否完全相同
|
||
*/
|
||
public static <K, V> boolean equalsElement(Map<K, V> map1, Map<K, V> map2) {
|
||
if (map1 == null && map2 == null) {
|
||
return true;
|
||
}
|
||
if (map1 == null || map2 == null) {
|
||
return false;
|
||
}
|
||
if (map1.size() != map2.size()) {
|
||
return false;
|
||
}
|
||
for (Map.Entry<K, V> en : map1.entrySet()) {
|
||
if (!Objects.equals(en.getValue(), map2.get(en.getKey()))) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 判断指定值是否包含指定的数组中,包含返回true
|
||
*
|
||
* @param values 集合
|
||
* @param value 单值
|
||
* @return boolean
|
||
*/
|
||
public static boolean contains(char[] values, char value) {
|
||
if (values == null) {
|
||
return false;
|
||
}
|
||
for (char v : values) {
|
||
if (v == value) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 判断指定值是否包含指定的数组中,包含返回true
|
||
*
|
||
* @param values 集合
|
||
* @param value 单值
|
||
* @return boolean
|
||
*/
|
||
public static boolean contains(short[] values, short value) {
|
||
if (values == null) {
|
||
return false;
|
||
}
|
||
for (short v : values) {
|
||
if (v == value) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 判断指定值(不要包含相同的元素)是否包含指定的数组中,包含返回true
|
||
*
|
||
* @param values 集合
|
||
* @param items 多值
|
||
* @return boolean
|
||
*/
|
||
public static boolean contains(short[] values, short... items) {
|
||
if (values == null) {
|
||
return false;
|
||
}
|
||
for (short item : items) {
|
||
if (!contains(values, item)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 判断指定值是否包含指定的数组中,包含返回true
|
||
*
|
||
* @param values 集合
|
||
* @param value 单值
|
||
* @return boolean
|
||
*/
|
||
public static boolean contains(int[] values, int value) {
|
||
if (values == null) {
|
||
return false;
|
||
}
|
||
for (int v : values) {
|
||
if (v == value) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 判断指定值(不要包含相同的元素)是否包含指定的数组中,包含返回true
|
||
*
|
||
* @param values 集合
|
||
* @param items 多值
|
||
* @return boolean
|
||
*/
|
||
public static boolean contains(int[] values, int... items) {
|
||
if (values == null) {
|
||
return false;
|
||
}
|
||
for (int item : items) {
|
||
if (!contains(values, item)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 判断指定值是否包含指定的数组中,包含返回true
|
||
*
|
||
* @param values 集合
|
||
* @param value 单值
|
||
* @return boolean
|
||
*/
|
||
public static boolean contains(long[] values, long value) {
|
||
if (values == null) {
|
||
return false;
|
||
}
|
||
for (long v : values) {
|
||
if (v == value) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 判断指定值(不要包含相同的元素)是否包含指定的数组中,包含返回true
|
||
*
|
||
* @param values 集合
|
||
* @param items 多值
|
||
* @return boolean
|
||
*/
|
||
public static boolean contains(long[] values, long... items) {
|
||
if (values == null) {
|
||
return false;
|
||
}
|
||
for (long item : items) {
|
||
if (!contains(values, item)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 判断指定值是否包含指定的数组中,包含返回true
|
||
*
|
||
* @param <T> 泛型
|
||
* @param values 集合
|
||
* @param value 单值
|
||
* @return boolean
|
||
*/
|
||
public static <T> boolean contains(T[] values, T value) {
|
||
if (values == null) {
|
||
return false;
|
||
}
|
||
for (T v : values) {
|
||
if (Objects.equals(v, value)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 判断指定值是否包含指定的数组中,包含返回true
|
||
*
|
||
* @param <T> 泛型
|
||
* @param values 集合
|
||
* @param predicate 过滤条件
|
||
* @return boolean
|
||
*/
|
||
public static <T> boolean contains(T[] values, Predicate<T> predicate) {
|
||
if (values == null) {
|
||
return false;
|
||
}
|
||
for (T v : values) {
|
||
if (predicate.test(v)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 判断指定值是否包含指定的数组中,包含返回true
|
||
*
|
||
* @param <T> 泛型
|
||
* @param values 集合
|
||
* @param predicate 过滤条件
|
||
* @return boolean
|
||
*/
|
||
public static <T> boolean contains(Collection<T> values, Predicate<T> predicate) {
|
||
if (values == null) {
|
||
return false;
|
||
}
|
||
for (T v : values) {
|
||
if (predicate.test(v)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 将指定的short元素是否数组中完全包含,重复元素的次数也要相同 <br>
|
||
* 例如: <br>
|
||
* containsMatch(new short[]{1, 2, 2, 3, 3, 3}, 1, 2, 3, 3) = true <br>
|
||
* containsMatch(new short[]{1, 2, 2, 3, 3, 3}, 1, 1, 2, 3, 3) = false <br>
|
||
*
|
||
* @param array 原数组
|
||
* @param items short[]
|
||
* @return 是否完全包含
|
||
*/
|
||
public static boolean containsMatch(final short[] array, final short... items) {
|
||
if (array == null) {
|
||
return false;
|
||
}
|
||
if (items == null || items.length == 0) {
|
||
return true;
|
||
}
|
||
if (array.length == 0 && items.length == 0) {
|
||
return true;
|
||
}
|
||
if (array.length < items.length) {
|
||
return false;
|
||
}
|
||
|
||
short[] subs = array;
|
||
for (short item : items) {
|
||
if (!contains(subs, item)) {
|
||
return false;
|
||
}
|
||
short[] newsubs = new short[subs.length - 1];
|
||
int k = 0;
|
||
boolean done = false;
|
||
for (short v : subs) {
|
||
if (done) {
|
||
newsubs[k++] = v;
|
||
} else if (v == item) {
|
||
done = true;
|
||
} else {
|
||
newsubs[k++] = v;
|
||
}
|
||
}
|
||
subs = newsubs;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 将指定的int元素是否数组中完全包含,重复元素的次数也要相同 <br>
|
||
* 例如: <br>
|
||
* containsMatch(new int[]{1, 2, 2, 3, 3, 3}, 1, 2, 3, 3) = true <br>
|
||
* containsMatch(new int[]{1, 2, 2, 3, 3, 3}, 1, 1, 2, 3, 3) = false <br>
|
||
*
|
||
* @param array 原数组
|
||
* @param items int[]
|
||
* @return 是否完全包含
|
||
*/
|
||
public static boolean containsMatch(final int[] array, final int... items) {
|
||
if (array == null) {
|
||
return false;
|
||
}
|
||
if (items == null || items.length == 0) {
|
||
return true;
|
||
}
|
||
if (array.length == 0 && items.length == 0) {
|
||
return true;
|
||
}
|
||
if (array.length < items.length) {
|
||
return false;
|
||
}
|
||
|
||
int[] subs = array;
|
||
for (int item : items) {
|
||
if (!contains(subs, item)) {
|
||
return false;
|
||
}
|
||
int[] newsubs = new int[subs.length - 1];
|
||
int k = 0;
|
||
boolean done = false;
|
||
for (int v : subs) {
|
||
if (done) {
|
||
newsubs[k++] = v;
|
||
} else if (v == item) {
|
||
done = true;
|
||
} else {
|
||
newsubs[k++] = v;
|
||
}
|
||
}
|
||
subs = newsubs;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 将指定的long元素是否数组中完全包含,重复元素的次数也要相同 <br>
|
||
* 例如: <br>
|
||
* containsMatch(new long[]{1, 2, 2, 3, 3, 3}, 1, 2, 3, 3) = true <br>
|
||
* containsMatch(new long[]{1, 2, 2, 3, 3, 3}, 1, 1, 2, 3, 3) = false <br>
|
||
*
|
||
* @param array 原数组
|
||
* @param items long[]
|
||
* @return 是否完全包含
|
||
*/
|
||
public static boolean containsMatch(final long[] array, final long... items) {
|
||
if (array == null) {
|
||
return false;
|
||
}
|
||
if (items == null || items.length == 0) {
|
||
return true;
|
||
}
|
||
if (array.length == 0 && items.length == 0) {
|
||
return true;
|
||
}
|
||
if (array.length < items.length) {
|
||
return false;
|
||
}
|
||
|
||
long[] subs = array;
|
||
for (long item : items) {
|
||
if (!contains(subs, item)) {
|
||
return false;
|
||
}
|
||
long[] newsubs = new long[subs.length - 1];
|
||
int k = 0;
|
||
boolean done = false;
|
||
for (long v : subs) {
|
||
if (done) {
|
||
newsubs[k++] = v;
|
||
} else if (v == item) {
|
||
done = true;
|
||
} else {
|
||
newsubs[k++] = v;
|
||
}
|
||
}
|
||
subs = newsubs;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 删除掉字符串数组中包含指定的字符串
|
||
*
|
||
* @param columns 待删除数组
|
||
* @param cols 需排除的字符串
|
||
* @return 新字符串数组
|
||
*/
|
||
public static String[] exclude(final String[] columns, final String... cols) {
|
||
if (columns == null || columns.length == 0 || cols == null || cols.length == 0) {
|
||
return columns;
|
||
}
|
||
int count = 0;
|
||
for (String column : columns) {
|
||
boolean flag = false;
|
||
for (String col : cols) {
|
||
if (column != null && column.equals(col)) {
|
||
flag = true;
|
||
break;
|
||
}
|
||
}
|
||
if (flag) {
|
||
count++;
|
||
}
|
||
}
|
||
if (count == 0) {
|
||
return columns;
|
||
}
|
||
if (count == columns.length) {
|
||
return new String[0];
|
||
}
|
||
final String[] newcols = new String[columns.length - count];
|
||
count = 0;
|
||
for (String column : columns) {
|
||
boolean flag = false;
|
||
for (String col : cols) {
|
||
if (column != null && column.equals(col)) {
|
||
flag = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!flag) {
|
||
newcols[count++] = column;
|
||
}
|
||
}
|
||
return newcols;
|
||
}
|
||
|
||
/**
|
||
* 查询指定对象, 没有返回null
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 数组
|
||
* @param predicate 查找器
|
||
* @return 对象
|
||
*/
|
||
public static <T> T find(final T[] array, final Predicate<T> predicate) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
for (T item : array) {
|
||
if (item != null && predicate.test(item)) {
|
||
return item;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 查询指定对象, 没有返回null
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 数组
|
||
* @param predicate 查找器
|
||
* @return 对象
|
||
*/
|
||
public static <T> T find(final Collection<T> array, final Predicate<T> predicate) {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
for (T item : array) {
|
||
if (item != null && predicate.test(item)) {
|
||
return item;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 查询指定对象位置, 没有返回-1
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 数组
|
||
* @param predicate 查找器
|
||
* @return 位置
|
||
*/
|
||
public static <T> int indexOf(final T[] array, final Predicate<T> predicate) {
|
||
if (array == null) {
|
||
return -1;
|
||
}
|
||
int index = -1;
|
||
for (T item : array) {
|
||
++index;
|
||
if (item != null && predicate.test(item)) {
|
||
return index;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 查询指定对象位置, 没有返回-1
|
||
*
|
||
* @param <T> 泛型
|
||
* @param array 数组
|
||
* @param predicate 查找器
|
||
* @return 位置
|
||
*/
|
||
public static <T> int indexOf(final Collection<T> array, final Predicate<T> predicate) {
|
||
if (array == null) {
|
||
return -1;
|
||
}
|
||
int index = -1;
|
||
for (T item : array) {
|
||
++index;
|
||
if (item != null && predicate.test(item)) {
|
||
return index;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final byte[] array, final byte element) {
|
||
if (array == null) {
|
||
return -1;
|
||
}
|
||
for (int i = 0; i < array.length; ++i) {
|
||
if (array[i] == element) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param fromIndex 起始位置,从0开始
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final byte[] array, int fromIndex, final byte element) {
|
||
if (array == null) {
|
||
return -1;
|
||
}
|
||
for (int i = fromIndex; i < array.length; ++i) {
|
||
if (array[i] == element) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final short[] array, final short element) {
|
||
return indexOf(array, 0, element);
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param fromIndex 起始位置,从0开始
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final short[] array, int fromIndex, final short element) {
|
||
if (array == null) {
|
||
return -1;
|
||
}
|
||
for (int i = fromIndex; i < array.length; ++i) {
|
||
if (array[i] == element) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final char[] array, final char element) {
|
||
return indexOf(array, 0, element);
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param fromIndex 起始位置,从0开始
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final char[] array, int fromIndex, final char element) {
|
||
if (array == null) {
|
||
return -1;
|
||
}
|
||
for (int i = fromIndex; i < array.length; ++i) {
|
||
if (array[i] == element) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final int[] array, final int element) {
|
||
return indexOf(array, 0, element);
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param fromIndex 起始位置,从0开始
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final int[] array, int fromIndex, final int element) {
|
||
if (array == null) {
|
||
return -1;
|
||
}
|
||
for (int i = fromIndex; i < array.length; ++i) {
|
||
if (array[i] == element) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final long[] array, final long element) {
|
||
return indexOf(array, 0, element);
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param fromIndex 起始位置,从0开始
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final long[] array, int fromIndex, final long element) {
|
||
if (array == null) {
|
||
return -1;
|
||
}
|
||
for (int i = fromIndex; i < array.length; ++i) {
|
||
if (array[i] == element) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final float[] array, final float element) {
|
||
return indexOf(array, 0, element);
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param fromIndex 起始位置,从0开始
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final float[] array, int fromIndex, final float element) {
|
||
if (array == null) {
|
||
return -1;
|
||
}
|
||
for (int i = fromIndex; i < array.length; ++i) {
|
||
if (array[i] == element) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final double[] array, final double element) {
|
||
return indexOf(array, 0, element);
|
||
}
|
||
|
||
/**
|
||
* 查询指定值位置, 没有返回-1
|
||
*
|
||
* @param array 数组
|
||
* @param fromIndex 起始位置,从0开始
|
||
* @param element 指定值
|
||
* @return 位置
|
||
*/
|
||
public static int indexOf(final double[] array, int fromIndex, final double element) {
|
||
if (array == null) {
|
||
return -1;
|
||
}
|
||
for (int i = fromIndex; i < array.length; ++i) {
|
||
if (array[i] == element) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* 将源对象转换成目标类型
|
||
*
|
||
* @param <T> 泛型
|
||
* @param type 目标类型
|
||
* @param value 源对象
|
||
* @return 对象
|
||
*/
|
||
@ClassDepends(Copier.class)
|
||
public static <T> T convertValue(Type type, Object value) {
|
||
if (type == null) {
|
||
return (T) value;
|
||
}
|
||
final Class typeClazz = TypeToken.typeToClass(type);
|
||
if (value == null) {
|
||
if (typeClazz == boolean.class) {
|
||
return (T) Boolean.FALSE;
|
||
} else if (typeClazz == byte.class) {
|
||
return (T) (Byte) (byte) 0;
|
||
} else if (typeClazz == char.class) {
|
||
return (T) (Character) (char) 0;
|
||
} else if (typeClazz == short.class) {
|
||
return (T) (Short) (short) 0;
|
||
} else if (typeClazz == int.class) {
|
||
return (T) (Integer) 0;
|
||
} else if (typeClazz == long.class) {
|
||
return (T) (Long) 0L;
|
||
} else if (typeClazz == float.class) {
|
||
return (T) (Float) 0F;
|
||
} else if (typeClazz == double.class) {
|
||
return (T) (Double) 0D;
|
||
}
|
||
return (T) value;
|
||
}
|
||
|
||
final Class valClazz = value.getClass();
|
||
if (typeClazz == valClazz || typeClazz.isAssignableFrom(valClazz)) {
|
||
return (T) value;
|
||
} else if (typeClazz == String.class) {
|
||
return (T) value.toString();
|
||
} else if (typeClazz == double.class || typeClazz == Double.class) {
|
||
if (value instanceof Number) {
|
||
return (T) (Number) ((Number) value).doubleValue();
|
||
} else if (valClazz == String.class) {
|
||
return (T) (Number) Double.parseDouble(value.toString());
|
||
}
|
||
} else if (typeClazz == float.class || typeClazz == Float.class) {
|
||
if (value instanceof Number) {
|
||
return (T) (Number) ((Number) value).floatValue();
|
||
} else if (valClazz == String.class) {
|
||
return (T) (Number) Float.parseFloat(value.toString());
|
||
}
|
||
} else if (typeClazz == long.class || typeClazz == Long.class) {
|
||
if (value instanceof Number) {
|
||
return (T) (Number) ((Number) value).longValue();
|
||
} else if (valClazz == String.class) {
|
||
return (T) (Number) Long.parseLong(value.toString());
|
||
}
|
||
} else if (typeClazz == int.class || typeClazz == Integer.class) {
|
||
if (value instanceof Number) {
|
||
return (T) (Number) ((Number) value).intValue();
|
||
} else if (valClazz == String.class) {
|
||
return (T) (Number) Integer.parseInt(value.toString());
|
||
}
|
||
} else if (typeClazz == short.class || typeClazz == Short.class) {
|
||
if (value instanceof Number) {
|
||
return (T) (Number) ((Number) value).shortValue();
|
||
} else if (valClazz == String.class) {
|
||
return (T) (Number) Short.parseShort(value.toString());
|
||
}
|
||
} else if (typeClazz == char.class || typeClazz == Character.class) {
|
||
if (value instanceof Number) {
|
||
char ch = (char) ((Number) value).intValue();
|
||
return (T) (Object) ch;
|
||
}
|
||
} else if (typeClazz == byte.class || typeClazz == Byte.class) {
|
||
if (value instanceof Number) {
|
||
return (T) (Number) ((Number) value).byteValue();
|
||
}
|
||
} else if (typeClazz == boolean.class || typeClazz == Boolean.class) {
|
||
if (value instanceof Number) {
|
||
return (T) (Object) (((Number) value).intValue() > 0);
|
||
}
|
||
} else if (typeClazz == BigInteger.class && valClazz == String.class) {
|
||
return (T) new BigInteger(value.toString());
|
||
} else if (typeClazz == BigDecimal.class && valClazz == String.class) {
|
||
return (T) new BigDecimal(value.toString());
|
||
}
|
||
JsonConvert convert = JsonConvert.root();
|
||
if (CharSequence.class.isAssignableFrom(valClazz)) {
|
||
return convert.convertFrom(type, value.toString());
|
||
} else {
|
||
return convert.convertFrom(type, convert.convertToBytes(value));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 将buffer的内容转换成字符串, string参数不为空时会追加在buffer内容字符串之前
|
||
*
|
||
* @param string 字符串前缀
|
||
* @param buffer ByteBuffer
|
||
* @return 字符串
|
||
*/
|
||
public static String toString(String string, ByteBuffer buffer) {
|
||
if (buffer == null || !buffer.hasRemaining()) {
|
||
return string;
|
||
}
|
||
int pos = buffer.position();
|
||
int limit = buffer.limit();
|
||
byte[] bytes = new byte[buffer.remaining()];
|
||
buffer.get(bytes);
|
||
buffer.position(pos);
|
||
buffer.limit(limit);
|
||
if (string == null) {
|
||
return new String(bytes, UTF_8);
|
||
}
|
||
return string + new String(bytes, UTF_8);
|
||
}
|
||
|
||
/**
|
||
* 将buffer的内容转换成字符串并打印到控制台, string参数不为空时会追加在buffer内容字符串之前
|
||
*
|
||
* @param string 字符串前缀
|
||
* @param buffer ByteBuffer
|
||
*/
|
||
public static void println(String string, ByteBuffer buffer) {
|
||
if (buffer == null || !buffer.hasRemaining()) {
|
||
return;
|
||
}
|
||
int pos = buffer.position();
|
||
int limit = buffer.limit();
|
||
byte[] bytes = new byte[buffer.remaining()];
|
||
buffer.get(bytes);
|
||
buffer.position(pos);
|
||
buffer.limit(limit);
|
||
println(string, bytes);
|
||
}
|
||
|
||
/**
|
||
* 将字节数组的内容转换成字符串并打印到控制台, string参数不为空时会追加在字节数组内容字符串之前
|
||
*
|
||
* @param string 字符串前缀
|
||
* @param bytes 字节数组
|
||
*/
|
||
public static void println(String string, byte... bytes) {
|
||
if (bytes == null) {
|
||
return;
|
||
}
|
||
StringBuilder sb = new StringBuilder();
|
||
if (string != null) {
|
||
sb.append(string);
|
||
}
|
||
sb.append(bytes.length).append(".[");
|
||
boolean last = false;
|
||
for (byte b : bytes) {
|
||
if (last) {
|
||
sb.append(',');
|
||
}
|
||
int v = b & 0xff;
|
||
sb.append("0x");
|
||
if (v < 16) {
|
||
sb.append('0');
|
||
}
|
||
sb.append(Integer.toHexString(v));
|
||
last = true;
|
||
}
|
||
sb.append(']');
|
||
(System.out).println(sb);
|
||
}
|
||
|
||
/**
|
||
* 返回本机的第一个内网IPv4地址, 没有则返回null
|
||
*
|
||
* @return IPv4地址
|
||
*/
|
||
public static InetAddress localInetAddress() {
|
||
InetAddress back = null;
|
||
try {
|
||
Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();
|
||
while (nifs.hasMoreElements()) {
|
||
NetworkInterface nif = nifs.nextElement();
|
||
if (!nif.isUp()) {
|
||
continue;
|
||
}
|
||
Enumeration<InetAddress> eis = nif.getInetAddresses();
|
||
while (eis.hasMoreElements()) {
|
||
InetAddress ia = eis.nextElement();
|
||
if (ia.isLoopbackAddress() && ia instanceof Inet4Address) {
|
||
back = ia;
|
||
}
|
||
if (ia.isSiteLocalAddress() && ia instanceof Inet4Address) {
|
||
return ia;
|
||
}
|
||
}
|
||
}
|
||
} catch (Exception e) {
|
||
// do nothing
|
||
}
|
||
return back;
|
||
}
|
||
|
||
/**
|
||
* 创建 CompletionHandler 对象
|
||
*
|
||
* @param <V> 结果对象的泛型
|
||
* @param <A> 附件对象的泛型
|
||
* @param success 成功的回调函数
|
||
* @param fail 失败的回调函数
|
||
* @return CompletionHandler
|
||
*/
|
||
public static <V, A> CompletionHandler<V, A> createAsyncHandler(
|
||
final BiConsumer<V, A> success, final BiConsumer<Throwable, A> fail) {
|
||
return new CompletionHandler<V, A>() {
|
||
@Override
|
||
public void completed(V result, A attachment) {
|
||
if (success != null) {
|
||
success.accept(result, attachment);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void failed(Throwable exc, A attachment) {
|
||
if (fail != null) {
|
||
fail.accept(exc, attachment);
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 创建没有返回结果的 CompletionHandler 对象
|
||
*
|
||
* @param <A> 附件对象的泛型
|
||
* @param success 成功的回调函数
|
||
* @param fail 失败的回调函数
|
||
* @return CompletionHandler
|
||
*/
|
||
public static <A> CompletionHandler<Void, A> createAsyncHandler(
|
||
final Consumer<A> success, final BiConsumer<Throwable, A> fail) {
|
||
return new CompletionHandler<Void, A>() {
|
||
@Override
|
||
public void completed(Void result, A attachment) {
|
||
if (success != null) {
|
||
success.accept(attachment);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void failed(Throwable exc, A attachment) {
|
||
if (fail != null) {
|
||
fail.accept(exc, attachment);
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 创建没有附件对象的 CompletionHandler 对象
|
||
*
|
||
* @param <V> 结果对象的泛型
|
||
* @param success 成功的回调函数
|
||
* @param fail 失败的回调函数
|
||
* @return CompletionHandler
|
||
*/
|
||
public static <V> CompletionHandler<V, Void> createAsyncHandler(
|
||
final Consumer<V> success, final Consumer<Throwable> fail) {
|
||
return new CompletionHandler<V, Void>() {
|
||
@Override
|
||
public void completed(V result, Void attachment) {
|
||
if (success != null) {
|
||
success.accept(result);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void failed(Throwable exc, Void attachment) {
|
||
if (fail != null) {
|
||
fail.accept(exc);
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 获取格式为yyyy-MM-dd HH:mm:ss的当前时间
|
||
*
|
||
* @return 格式为yyyy-MM-dd HH:mm:ss的时间值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static String now() {
|
||
return Times.now();
|
||
}
|
||
|
||
/**
|
||
* 获取格式为yyyy-MM-dd HH:mm:ss.fff的当前时间
|
||
*
|
||
* @return 格式为yyyy-MM-dd HH:mm:ss.fff的时间值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static String nowMillis() {
|
||
return Times.nowMillis();
|
||
}
|
||
|
||
/**
|
||
* 将指定时间格式化为 yyyy-MM-dd HH:mm:ss
|
||
*
|
||
* @param time 待格式化的时间
|
||
* @return 格式为yyyy-MM-dd HH:mm:ss的时间值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static String formatTime(long time) {
|
||
return Times.formatTime(time);
|
||
}
|
||
|
||
/**
|
||
* 将时间值转换为长度为9的36进制值
|
||
*
|
||
* @param time 时间值
|
||
* @return 36进制时间值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static String format36time(long time) {
|
||
return Times.format36time(time);
|
||
}
|
||
|
||
/**
|
||
* 获取当天凌晨零点的格林时间
|
||
*
|
||
* @return 毫秒数
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static long midnight() {
|
||
return Times.midnight();
|
||
}
|
||
|
||
/**
|
||
* 获取指定时间当天凌晨零点的格林时间
|
||
*
|
||
* @param time 指定时间
|
||
* @return 毫秒数
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static long midnight(long time) {
|
||
return Times.midnight(time);
|
||
}
|
||
|
||
/**
|
||
* 获取当天20151231格式的int值
|
||
*
|
||
* @return 20151231格式的int值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static int today() {
|
||
return Times.today();
|
||
}
|
||
|
||
/**
|
||
* 获取当天151231格式的int值
|
||
*
|
||
* @return 151231格式的int值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static int todayYYMMDD() {
|
||
return Times.todayYYMMDD();
|
||
}
|
||
|
||
/**
|
||
* 获取当天1512312359格式的int值
|
||
*
|
||
* @return 1512312359格式的int值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static int todayYYMMDDHHmm() {
|
||
return Times.todayYYMMDDHHmm();
|
||
}
|
||
|
||
/**
|
||
* 获取当天20151231235959格式的int值
|
||
*
|
||
* @return 20151231235959格式的int值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static long todayYYYYMMDDHHmmss() {
|
||
return Times.todayYYYYMMDDHHmmss();
|
||
}
|
||
|
||
/**
|
||
* 获取当天151231235959格式的int值
|
||
*
|
||
* @return 151231235959格式的int值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static long todayYYMMDDHHmmss() {
|
||
return Times.todayYYMMDDHHmmss();
|
||
}
|
||
|
||
/**
|
||
* 获取明天20151230格式的int值
|
||
*
|
||
* @return 20151230格式的int值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static int tomorrow() {
|
||
return Times.tomorrow();
|
||
}
|
||
|
||
/**
|
||
* 获取明天151230格式的int值
|
||
*
|
||
* @return 151230格式的int值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static int tomorrowYYMMDD() {
|
||
return Times.tomorrowYYMMDD();
|
||
}
|
||
|
||
/**
|
||
* 获取昨天20151230格式的int值
|
||
*
|
||
* @return 20151230格式的int值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static int yesterday() {
|
||
return Times.yesterday();
|
||
}
|
||
|
||
/**
|
||
* 获取昨天151230格式的int值
|
||
*
|
||
* @return 151230格式的int值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static int yesterdayYYMMDD() {
|
||
return Times.yesterdayYYMMDD();
|
||
}
|
||
|
||
/**
|
||
* 获取指定时间的20160202格式的int值
|
||
*
|
||
* @param time 指定时间
|
||
* @return 毫秒数
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static int yyyyMMdd(long time) {
|
||
return Times.yyyyMMdd(time);
|
||
}
|
||
|
||
/**
|
||
* 获取指定时间的160202格式的int值
|
||
*
|
||
* @param time 指定时间
|
||
* @return 毫秒数
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static int yyMMdd(long time) {
|
||
return Times.yyMMdd(time);
|
||
}
|
||
|
||
/**
|
||
* 获取当天16020223格式的int值
|
||
*
|
||
* @param time 指定时间
|
||
* @return 16020223格式的int值
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static int yyMMDDHHmm(long time) {
|
||
return Times.yyMMDDHHmm(time);
|
||
}
|
||
|
||
/**
|
||
* 获取时间点所在星期的周一
|
||
*
|
||
* @param time 指定时间
|
||
* @return 毫秒数
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static long monday(long time) {
|
||
return Times.monday(time);
|
||
}
|
||
|
||
/**
|
||
* 获取时间点所在星期的周日
|
||
*
|
||
* @param time 指定时间
|
||
* @return 毫秒数
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static long sunday(long time) {
|
||
return Times.sunday(time);
|
||
}
|
||
|
||
/**
|
||
* 获取时间点所在月份的1号
|
||
*
|
||
* @param time 指定时间
|
||
* @return 毫秒数
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static long monthFirstDay(long time) {
|
||
return Times.monthFirstDay(time);
|
||
}
|
||
|
||
/**
|
||
* 获取时间点所在月份的最后一天
|
||
*
|
||
* @param time 指定时间
|
||
* @return 毫秒数
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static long monthLastDay(long time) {
|
||
return Times.monthLastDay(time);
|
||
}
|
||
|
||
/**
|
||
* 将时间格式化, 支持%1$ty 和 %ty两种格式
|
||
*
|
||
* @param format 格式
|
||
* @param size 带%t的个数,值小于0则需要计算
|
||
* @param time 时间
|
||
* @since 2.7.0
|
||
* @return 时间格式化
|
||
*/
|
||
@Deprecated(since = "2.8.0")
|
||
public static String formatTime(String format, int size, Object time) {
|
||
return Times.formatTime(format, size, time);
|
||
}
|
||
|
||
/**
|
||
* 将int[]强制转换成byte[]
|
||
*
|
||
* @param value int[]
|
||
* @return byte[]
|
||
*/
|
||
public static byte[] intsToBytes(int[] value) {
|
||
if (value == null) {
|
||
return null;
|
||
}
|
||
byte[] bs = new byte[value.length];
|
||
for (int i = 0; i < bs.length; i++) {
|
||
bs[i] = (byte) value[i];
|
||
}
|
||
return bs;
|
||
}
|
||
|
||
/**
|
||
* MD5加密
|
||
*
|
||
* @param str 待加密数据
|
||
* @return md5值
|
||
*/
|
||
public static String md5Hex(String str) {
|
||
return binToHexString(md5(str));
|
||
}
|
||
|
||
/**
|
||
* MD5加密
|
||
*
|
||
* @param input 待加密数据
|
||
* @return md5值
|
||
*/
|
||
public static String md5Hex(byte[] input) {
|
||
return binToHexString(md5(input));
|
||
}
|
||
|
||
/**
|
||
* MD5加密
|
||
*
|
||
* @param str 待加密数据
|
||
* @return md5值
|
||
*/
|
||
public static byte[] md5(String str) {
|
||
if (str == null) {
|
||
return null;
|
||
}
|
||
MessageDigest md5;
|
||
try {
|
||
md5 = MessageDigest.getInstance("MD5");
|
||
} catch (NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException("Couldn't find a MD5 provider", ex);
|
||
}
|
||
return md5.digest(str.getBytes(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
/**
|
||
* MD5加密
|
||
*
|
||
* @param input 待加密数据
|
||
* @return md5值
|
||
*/
|
||
public static byte[] md5(byte[] input) {
|
||
if (input == null) {
|
||
return null;
|
||
}
|
||
MessageDigest md5;
|
||
try {
|
||
md5 = MessageDigest.getInstance("MD5");
|
||
} catch (NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException("Couldn't find a MD5 provider", ex);
|
||
}
|
||
return md5.digest(input);
|
||
}
|
||
|
||
/**
|
||
* MD5加密
|
||
*
|
||
* @param input 待加密数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return md5值
|
||
*/
|
||
public static byte[] md5(byte[] input, int offset, int len) {
|
||
if (input == null) {
|
||
return null;
|
||
}
|
||
MessageDigest md5;
|
||
try {
|
||
md5 = MessageDigest.getInstance("MD5");
|
||
md5.update(input, offset, len);
|
||
return md5.digest();
|
||
} catch (NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException("Couldn't find a MD5 provider", ex);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* SHA-256
|
||
*
|
||
* @param str 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String sha256Hex(String str) {
|
||
return binToHexString(sha256(str));
|
||
}
|
||
|
||
/**
|
||
* SHA-256
|
||
*
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String sha256Hex(byte[] input) {
|
||
return binToHexString(sha256(input));
|
||
}
|
||
|
||
/**
|
||
* SHA-256
|
||
*
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static String sha256Hex(byte[] input, int offset, int len) {
|
||
return binToHexString(sha256(input, offset, len));
|
||
}
|
||
|
||
/**
|
||
* 以0x开头的 SHA-256
|
||
*
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String sha256Hex0x(byte[] input) {
|
||
return binTo0xHexString(sha256(input));
|
||
}
|
||
|
||
/**
|
||
* 以0x开头的 SHA-256
|
||
*
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static String sha256Hex0x(byte[] input, int offset, int len) {
|
||
return binTo0xHexString(sha256(input, offset, len));
|
||
}
|
||
|
||
/**
|
||
* SHA-256
|
||
*
|
||
* @param str 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static byte[] sha256(String str) {
|
||
if (str == null) {
|
||
return null;
|
||
}
|
||
MessageDigest digester;
|
||
try {
|
||
digester = MessageDigest.getInstance("SHA-256");
|
||
} catch (NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException("Couldn't find a SHA-256 provider", ex);
|
||
}
|
||
return digester.digest(str.getBytes(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
/**
|
||
* SHA-256
|
||
*
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static byte[] sha256(byte[] input) {
|
||
if (input == null) {
|
||
return null;
|
||
}
|
||
MessageDigest digester;
|
||
try {
|
||
digester = MessageDigest.getInstance("SHA-256");
|
||
} catch (NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException(ex);
|
||
}
|
||
return digester.digest(input);
|
||
}
|
||
|
||
/**
|
||
* SHA-256
|
||
*
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static byte[] sha256(byte[] input, int offset, int len) {
|
||
if (input == null) {
|
||
return null;
|
||
}
|
||
MessageDigest digester;
|
||
try {
|
||
digester = MessageDigest.getInstance("SHA-256");
|
||
digester.update(input, offset, len);
|
||
return digester.digest();
|
||
} catch (Exception ex) {
|
||
throw new RedkaleException(ex);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* HmacSHA1
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha1Base64(String key, String input) {
|
||
return Base64.getEncoder().encodeToString(hmacSha1(key.getBytes(UTF_8), input.getBytes(UTF_8)));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA1
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha1Base64(byte[] key, byte[] input) {
|
||
return Base64.getEncoder().encodeToString(hmacSha1(key, input));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA1
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha1Base64(byte[] key, byte[] input, int offset, int len) {
|
||
return Base64.getEncoder().encodeToString(hmacSha1(key, input, offset, len));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA1
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha1Hex(byte[] key, byte[] input) {
|
||
return binToHexString(hmacSha1(key, input));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA1
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha1Hex(byte[] key, byte[] input, int offset, int len) {
|
||
return binToHexString(hmacSha1(key, input, offset, len));
|
||
}
|
||
|
||
/**
|
||
* 以0x开头的 HmacSHA1
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha1Hex0x(byte[] key, byte[] input) {
|
||
return binTo0xHexString(hmacSha1(key, input));
|
||
}
|
||
|
||
/**
|
||
* 以0x开头的 HmacSHA1
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha1Hex0x(byte[] key, byte[] input, int offset, int len) {
|
||
return binTo0xHexString(hmacSha1(key, input, offset, len));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA1
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static byte[] hmacSha1(byte[] key, byte[] input) {
|
||
if (input == null) {
|
||
return null;
|
||
}
|
||
try {
|
||
Mac mac = Mac.getInstance("HmacSHA1");
|
||
mac.init(new SecretKeySpec(key, "HmacSHA1"));
|
||
return mac.doFinal(input);
|
||
} catch (InvalidKeyException | NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException(ex);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* HmacSHA1
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static byte[] hmacSha1(byte[] key, byte[] input, int offset, int len) {
|
||
if (input == null) {
|
||
return null;
|
||
}
|
||
try {
|
||
Mac mac = Mac.getInstance("HmacSHA1");
|
||
mac.init(new SecretKeySpec(key, "HmacSHA1"));
|
||
mac.update(input, offset, len);
|
||
return mac.doFinal();
|
||
} catch (InvalidKeyException | NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException(ex);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* HmacSHA256
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha256Base64(String key, String input) {
|
||
return Base64.getEncoder().encodeToString(hmacSha256(key.getBytes(UTF_8), input.getBytes(UTF_8)));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA256
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha256Base64(byte[] key, byte[] input) {
|
||
return Base64.getEncoder().encodeToString(hmacSha256(key, input));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA256
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha256Base64(byte[] key, byte[] input, int offset, int len) {
|
||
return Base64.getEncoder().encodeToString(hmacSha256(key, input, offset, len));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA256
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha256Hex(byte[] key, byte[] input) {
|
||
return binToHexString(hmacSha256(key, input));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA256
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha256Hex(byte[] key, byte[] input, int offset, int len) {
|
||
return binToHexString(hmacSha256(key, input, offset, len));
|
||
}
|
||
|
||
/**
|
||
* 以0x开头的 HmacSHA256
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha256Hex0x(byte[] key, byte[] input) {
|
||
return binTo0xHexString(hmacSha256(key, input));
|
||
}
|
||
|
||
/**
|
||
* 以0x开头的 HmacSHA256
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha256Hex0x(byte[] key, byte[] input, int offset, int len) {
|
||
return binTo0xHexString(hmacSha256(key, input, offset, len));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA256
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static byte[] hmacSha256(byte[] key, byte[] input) {
|
||
if (input == null) {
|
||
return null;
|
||
}
|
||
try {
|
||
Mac mac = Mac.getInstance("HmacSHA256");
|
||
mac.init(new SecretKeySpec(key, "HmacSHA256"));
|
||
return mac.doFinal(input);
|
||
} catch (InvalidKeyException | NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException(ex);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* HmacSHA256
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static byte[] hmacSha256(byte[] key, byte[] input, int offset, int len) {
|
||
if (input == null) {
|
||
return null;
|
||
}
|
||
try {
|
||
Mac mac = Mac.getInstance("HmacSHA256");
|
||
mac.init(new SecretKeySpec(key, "HmacSHA256"));
|
||
mac.update(input, offset, len);
|
||
return mac.doFinal();
|
||
} catch (InvalidKeyException | NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException(ex);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* HmacSHA512
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha512Base64(String key, String input) {
|
||
return Base64.getEncoder().encodeToString(hmacSha512(key.getBytes(UTF_8), input.getBytes(UTF_8)));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA512
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha512Base64(byte[] key, byte[] input) {
|
||
return Base64.getEncoder().encodeToString(hmacSha512(key, input));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA512
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha512Base64(byte[] key, byte[] input, int offset, int len) {
|
||
return Base64.getEncoder().encodeToString(hmacSha512(key, input, offset, len));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA512
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha512Hex(byte[] key, byte[] input) {
|
||
return binToHexString(hmacSha512(key, input));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA512
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha512Hex(byte[] key, byte[] input, int offset, int len) {
|
||
return binToHexString(hmacSha512(key, input, offset, len));
|
||
}
|
||
|
||
/**
|
||
* 以0x开头的 HmacSHA512
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha512Hex0x(byte[] key, byte[] input) {
|
||
return binTo0xHexString(hmacSha512(key, input));
|
||
}
|
||
|
||
/**
|
||
* 以0x开头的 HmacSHA512
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static String hmacSha512Hex0x(byte[] key, byte[] input, int offset, int len) {
|
||
return binTo0xHexString(hmacSha512(key, input, offset, len));
|
||
}
|
||
|
||
/**
|
||
* HmacSHA512
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static byte[] hmacSha512(byte[] key, byte[] input) {
|
||
if (input == null) {
|
||
return null;
|
||
}
|
||
try {
|
||
SecretKey sk = new SecretKeySpec(key, "HmacSHA512");
|
||
Mac mac = Mac.getInstance("HmacSHA512");
|
||
mac.init(sk);
|
||
return mac.doFinal(input);
|
||
} catch (InvalidKeyException | NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException(ex);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* HmacSHA512
|
||
*
|
||
* @param key 密钥
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return hash值
|
||
*/
|
||
public static byte[] hmacSha512(byte[] key, byte[] input, int offset, int len) {
|
||
if (input == null) {
|
||
return null;
|
||
}
|
||
try {
|
||
SecretKey sk = new SecretKeySpec(key, "HmacSHA512");
|
||
Mac mac = Mac.getInstance("HmacSHA512");
|
||
mac.init(sk);
|
||
mac.update(input, offset, len);
|
||
return mac.doFinal();
|
||
} catch (InvalidKeyException | NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException(ex);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 根据指定算法进行hash
|
||
*
|
||
* @param algorithm 算法名
|
||
* @param input 待hash数据
|
||
* @return hash值
|
||
*/
|
||
public static byte[] hash(String algorithm, byte[] input) {
|
||
try {
|
||
MessageDigest digest = MessageDigest.getInstance(algorithm.toUpperCase());
|
||
return digest.digest(input);
|
||
} catch (NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException("Couldn't find a " + algorithm + " provider", ex);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 根据指定算法进行hash
|
||
*
|
||
* @param algorithm 算法名
|
||
* @param input 待hash数据
|
||
* @param offset 偏移量
|
||
* @param length 长度
|
||
* @return hash值
|
||
*/
|
||
public static byte[] hash(String algorithm, byte[] input, int offset, int length) {
|
||
try {
|
||
MessageDigest digest = MessageDigest.getInstance(algorithm.toUpperCase());
|
||
digest.update(input, offset, length);
|
||
return digest.digest();
|
||
} catch (NoSuchAlgorithmException ex) {
|
||
throw new RedkaleException("Couldn't find a " + algorithm + " provider", ex);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 随机
|
||
*
|
||
* @return 随机
|
||
*/
|
||
public static SecureRandom secureRandom() {
|
||
return random;
|
||
}
|
||
|
||
/**
|
||
* 生成随机数
|
||
*
|
||
* @param size 随机数长度
|
||
* @return 随机数
|
||
*/
|
||
public static byte[] generateRandomBytes(int size) {
|
||
byte[] bytes = new byte[size];
|
||
random.nextBytes(bytes);
|
||
return bytes;
|
||
}
|
||
|
||
/**
|
||
* 将字节数组转换为以0x开头的16进制字符串
|
||
*
|
||
* @param bytes 字节数组
|
||
* @return 16进制字符串
|
||
*/
|
||
public static String binTo0xHexString(byte[] bytes) {
|
||
return "0x" + new String(binToHex(bytes));
|
||
}
|
||
|
||
/**
|
||
* 将字节数组转换为以0x开头的16进制字符串
|
||
*
|
||
* @param bytes 字节数组
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return 16进制字符串
|
||
*/
|
||
public static String binTo0xHexString(byte[] bytes, int offset, int len) {
|
||
return "0x" + new String(binToHex(bytes, offset, len));
|
||
}
|
||
|
||
/**
|
||
* 将字节数组转换为16进制字符串
|
||
*
|
||
* @param bytes 字节数组
|
||
* @return 16进制字符串
|
||
*/
|
||
public static String binToHexString(byte[] bytes) {
|
||
return new String(binToHex(bytes));
|
||
}
|
||
|
||
/**
|
||
* 将字节数组转换为16进制字符数组
|
||
*
|
||
* @param bytes 字节数组
|
||
* @return 16进制字符串的字符数组
|
||
*/
|
||
public static char[] binToHex(byte[] bytes) {
|
||
return binToHex(bytes, 0, bytes.length);
|
||
}
|
||
|
||
/**
|
||
* 将字节数组转换为16进制字符串
|
||
*
|
||
* @param bytes 字节数组
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return 16进制字符串
|
||
*/
|
||
public static String binToHexString(byte[] bytes, int offset, int len) {
|
||
return new String(binToHex(bytes, offset, len));
|
||
}
|
||
|
||
/**
|
||
* 将字节数组转换为16进制字符数组
|
||
*
|
||
* @param bytes 字节数组
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return 16进制字符串的字符数组
|
||
*/
|
||
public static char[] binToHex(byte[] bytes, int offset, int len) {
|
||
final char[] sb = new char[len * 2];
|
||
final int end = offset + len;
|
||
int index = 0;
|
||
final char[] hexs = hex;
|
||
for (int i = offset; i < end; i++) {
|
||
byte b = bytes[i];
|
||
sb[index++] = (hexs[((b >> 4) & 0xF)]);
|
||
sb[index++] = hexs[((b) & 0xF)];
|
||
}
|
||
return sb;
|
||
}
|
||
|
||
/**
|
||
* 将16进制字符串转换成字节数组
|
||
*
|
||
* @param src 16进制字符串
|
||
* @return 字节数组
|
||
*/
|
||
public static byte[] hexToBin(CharSequence src) {
|
||
return hexToBin(src, 0, src.length());
|
||
}
|
||
|
||
/**
|
||
* 将16进制字符串转换成字节数组
|
||
*
|
||
* @param src 16进制字符串
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return 字节数组
|
||
*/
|
||
public static byte[] hexToBin(CharSequence src, int offset, int len) {
|
||
if (offset == 0 && src.length() > 2 && src.charAt(0) == '0' && (src.charAt(1) == 'x' || src.charAt(1) == 'X')) {
|
||
offset += 2;
|
||
len -= 2;
|
||
}
|
||
final int size = (len + 1) / 2;
|
||
final byte[] bytes = new byte[size];
|
||
String digits = "0123456789abcdef";
|
||
for (int i = 0; i < size; i++) {
|
||
int ch1 = src.charAt(offset + i * 2);
|
||
if ('A' <= ch1 && 'F' >= ch1) {
|
||
ch1 = ch1 - 'A' + 'a';
|
||
}
|
||
int ch2 = src.charAt(offset + i * 2 + 1);
|
||
if ('A' <= ch2 && 'F' >= ch2) {
|
||
ch2 = ch2 - 'A' + 'a';
|
||
}
|
||
int pos1 = digits.indexOf(ch1);
|
||
if (pos1 < 0) {
|
||
throw new NumberFormatException();
|
||
}
|
||
int pos2 = digits.indexOf(ch2);
|
||
if (pos2 < 0) {
|
||
throw new NumberFormatException();
|
||
}
|
||
bytes[i] = (byte) (pos1 * 0x10 + pos2);
|
||
}
|
||
return bytes;
|
||
}
|
||
|
||
/**
|
||
* 将16进制字符串转换成字节数组
|
||
*
|
||
* @param str 16进制字符串
|
||
* @return 字节数组
|
||
*/
|
||
public static byte[] hexToBin(String str) {
|
||
return hexToBin(charArray(str));
|
||
}
|
||
|
||
/**
|
||
* 将16进制字符数组转换成字节数组
|
||
*
|
||
* @param src 16进制字符数组
|
||
* @return 字节数组
|
||
*/
|
||
public static byte[] hexToBin(char[] src) {
|
||
return hexToBin(src, 0, src.length);
|
||
}
|
||
|
||
/**
|
||
* 将16进制字符数组转换成字节数组
|
||
*
|
||
* @param src 16进制字符数组
|
||
* @param offset 偏移量
|
||
* @param len 长度
|
||
* @return 字节数组
|
||
*/
|
||
public static byte[] hexToBin(char[] src, int offset, int len) {
|
||
if (offset == 0 && src.length > 2 && src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) {
|
||
offset += 2;
|
||
len -= 2;
|
||
}
|
||
final int size = (len + 1) / 2;
|
||
final byte[] bytes = new byte[size];
|
||
String digits = "0123456789abcdef";
|
||
for (int i = 0; i < size; i++) {
|
||
int ch1 = src[offset + i * 2];
|
||
if ('A' <= ch1 && 'F' >= ch1) {
|
||
ch1 = ch1 - 'A' + 'a';
|
||
}
|
||
int ch2 = src[offset + i * 2 + 1];
|
||
if ('A' <= ch2 && 'F' >= ch2) {
|
||
ch2 = ch2 - 'A' + 'a';
|
||
}
|
||
int pos1 = digits.indexOf(ch1);
|
||
if (pos1 < 0) {
|
||
throw new NumberFormatException();
|
||
}
|
||
int pos2 = digits.indexOf(ch2);
|
||
if (pos2 < 0) {
|
||
throw new NumberFormatException();
|
||
}
|
||
bytes[i] = (byte) (pos1 * 0x10 + pos2);
|
||
}
|
||
return bytes;
|
||
}
|
||
|
||
// -----------------------------------------------------------------------------
|
||
/**
|
||
* 使用UTF-8编码将byte[]转换成char[]
|
||
*
|
||
* @param array byte[]
|
||
* @return char[]
|
||
*/
|
||
public static char[] decodeUTF8(final byte[] array) {
|
||
return decodeUTF8(array, 0, array.length);
|
||
}
|
||
|
||
public static char[] decodeUTF8(final byte[] array, final int start, final int len) {
|
||
byte b;
|
||
int size = len;
|
||
final byte[] bytes = array;
|
||
final int limit = start + len;
|
||
for (int i = start; i < limit; i++) {
|
||
b = bytes[i];
|
||
if ((b >> 5) == -2) { // 2 bytes, 11 bits: 110xxxxx 10xxxxxx
|
||
size--;
|
||
} else if ((b >> 4) == -2) { // 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
|
||
size -= 2;
|
||
} else if ((b >> 3) == -2) { // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||
size -= 2;
|
||
}
|
||
}
|
||
final char[] text = new char[size];
|
||
size = 0;
|
||
for (int i = start; i < limit; ) {
|
||
b = bytes[i++];
|
||
if (b >= 0) { // 1 byte, 7 bits: 0xxxxxxx
|
||
text[size++] = (char) b;
|
||
} else if ((b >> 5) == -2) { // 2 bytes, 11 bits: 110xxxxx 10xxxxxx
|
||
text[size++] = (char) (((b << 6) ^ bytes[i++]) ^ (((byte) 0xC0 << 6) ^ ((byte) 0x80)));
|
||
} else if ((b >> 4) == -2) { // 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
|
||
text[size++] = (char) ((b << 12)
|
||
^ (bytes[i++] << 6)
|
||
^ (bytes[i++] ^ (((byte) 0xE0 << 12) ^ ((byte) 0x80 << 6) ^ ((byte) 0x80))));
|
||
} else if ((b >> 3) == -2) { // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||
int uc = ((b << 18)
|
||
^ (bytes[i++] << 12)
|
||
^ (bytes[i++] << 6)
|
||
^ (bytes[i++]
|
||
^ (((byte) 0xF0 << 18) ^ ((byte) 0x80 << 12) ^ ((byte) 0x80 << 6) ^ ((byte) 0x80))));
|
||
text[size++] = Character.highSurrogate(uc);
|
||
text[size++] = Character.lowSurrogate(uc);
|
||
// 测试代码 byte[] bs = {(byte)34, (byte)76, (byte)105, (byte)108, (byte)121, (byte)240, (byte)159,
|
||
// (byte)146, (byte)171, (byte)34};
|
||
}
|
||
}
|
||
return text;
|
||
}
|
||
|
||
public static byte[] encodeUTF8(final String value) {
|
||
if (value == null) {
|
||
return new byte[0];
|
||
}
|
||
return encodeUTF8(value.toCharArray());
|
||
}
|
||
|
||
public static byte[] encodeUTF8(final char[] array) {
|
||
return encodeUTF8(array, 0, array.length);
|
||
}
|
||
|
||
public static byte[] encodeUTF8(final char[] text, final int start, final int len) {
|
||
char c;
|
||
int size = 0;
|
||
final char[] chs = text;
|
||
final int limit = start + len;
|
||
for (int i = start; i < limit; i++) {
|
||
c = chs[i];
|
||
if (c < 0x80) {
|
||
size++;
|
||
} else if (c < 0x800) {
|
||
size += 2;
|
||
} else if (Character.isSurrogate(c)) {
|
||
size += 2;
|
||
} else {
|
||
size += 3;
|
||
}
|
||
}
|
||
final byte[] bytes = new byte[size];
|
||
size = 0;
|
||
for (int i = start; i < limit; i++) {
|
||
c = chs[i];
|
||
if (c < 0x80) {
|
||
bytes[size++] = (byte) c;
|
||
} else if (c < 0x800) {
|
||
bytes[size++] = (byte) (0xc0 | (c >> 6));
|
||
bytes[size++] = (byte) (0x80 | (c & 0x3f));
|
||
} else if (Character.isSurrogate(c)) { // 连取两个
|
||
int uc = Character.toCodePoint(c, chs[i + 1]);
|
||
bytes[size++] = (byte) (0xf0 | ((uc >> 18)));
|
||
bytes[size++] = (byte) (0x80 | ((uc >> 12) & 0x3f));
|
||
bytes[size++] = (byte) (0x80 | ((uc >> 6) & 0x3f));
|
||
bytes[size++] = (byte) (0x80 | (uc & 0x3f));
|
||
i++;
|
||
} else {
|
||
bytes[size++] = (byte) (0xe0 | ((c >> 12)));
|
||
bytes[size++] = (byte) (0x80 | ((c >> 6) & 0x3f));
|
||
bytes[size++] = (byte) (0x80 | (c & 0x3f));
|
||
}
|
||
}
|
||
return bytes;
|
||
}
|
||
|
||
public static long getAddress(ByteBuffer buffer) {
|
||
return bufferAddrFunction.applyAsLong(buffer);
|
||
}
|
||
|
||
public static boolean isLatin1(String value) {
|
||
if (value == null) {
|
||
return true;
|
||
}
|
||
if (strLatin1Function != null) {
|
||
return strLatin1Function.test(value); // LATIN1:0 UTF16:1
|
||
}
|
||
char[] chs = charArray(value);
|
||
for (char ch : chs) {
|
||
if (ch >= 0x80) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
public static byte[] byteUTF16Array(String value) {
|
||
if (value == null || strByteFunction == null) {
|
||
return null;
|
||
}
|
||
return strByteFunction.apply(value);
|
||
}
|
||
|
||
public static char[] charArray(String value) {
|
||
if (value == null) {
|
||
return null;
|
||
}
|
||
return value.toCharArray();
|
||
}
|
||
|
||
public static char[] charArray(StringBuilder value) {
|
||
if (value == null) {
|
||
return null;
|
||
}
|
||
return value.toString().toCharArray();
|
||
}
|
||
|
||
// 只能是单字节字符串
|
||
public static byte[] latin1ByteArray(String latin1Value) {
|
||
if (latin1Value == null) {
|
||
return null;
|
||
}
|
||
if (strByteFunction == null) {
|
||
return latin1Value.getBytes();
|
||
}
|
||
return strByteFunction.apply(latin1Value);
|
||
}
|
||
|
||
// 只能是单字节字符串
|
||
public static byte[] latin1ByteArray(StringBuilder latin1Value) {
|
||
if (latin1Value == null) {
|
||
return null;
|
||
}
|
||
if (sbByteFunction == null) {
|
||
return latin1Value.toString().getBytes();
|
||
}
|
||
return sbByteFunction.apply(latin1Value);
|
||
}
|
||
|
||
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, final char[] array) {
|
||
return encodeUTF8(buffer, array, 0, array.length);
|
||
}
|
||
|
||
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, int bytesLength, final char[] array) {
|
||
return encodeUTF8(buffer, bytesLength, array, 0, array.length);
|
||
}
|
||
|
||
public static int encodeUTF8Length(String value) {
|
||
if (value == null) {
|
||
return -1;
|
||
}
|
||
return encodeUTF8Length(value.toCharArray());
|
||
}
|
||
|
||
public static int encodeUTF8Length(final char[] text) {
|
||
return encodeUTF8Length(text, 0, text.length);
|
||
}
|
||
|
||
public static int encodeUTF8Length(final char[] text, final int start, final int len) {
|
||
char c;
|
||
int size = 0;
|
||
final char[] chs = text;
|
||
final int limit = start + len;
|
||
for (int i = start; i < limit; i++) {
|
||
c = chs[i];
|
||
if (c < 0x80) {
|
||
size++;
|
||
} else if (c < 0x800) {
|
||
size += 2;
|
||
} else if (Character.isSurrogate(c)) {
|
||
size += 2;
|
||
} else {
|
||
size += 3;
|
||
}
|
||
}
|
||
return size;
|
||
}
|
||
|
||
/**
|
||
* 将两个数字组装成一个long
|
||
*
|
||
* @param high 高位值
|
||
* @param low 低位值
|
||
* @return long值
|
||
*/
|
||
public static long merge(int high, int low) {
|
||
return (0L + high) << 32 | low;
|
||
}
|
||
|
||
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, final char[] text, final int start, final int len) {
|
||
return encodeUTF8(buffer, encodeUTF8Length(text, start, len), text, start, len);
|
||
}
|
||
|
||
// 返回的ByteBuffer为扩展buffer,为null表示参数中的buffer足够存储数据
|
||
public static ByteBuffer encodeUTF8(
|
||
final ByteBuffer buffer, int bytesLength, final char[] text, final int start, final int len) {
|
||
char c;
|
||
char[] chs = text;
|
||
final int limit = start + len;
|
||
int remain = buffer.remaining();
|
||
final ByteBuffer buffer2 =
|
||
remain >= bytesLength ? null : ByteBuffer.allocate(bytesLength - remain + 4); // 最差情况buffer最后两byte没有填充
|
||
ByteBuffer buf = buffer;
|
||
for (int i = start; i < limit; i++) {
|
||
c = chs[i];
|
||
if (c < 0x80) {
|
||
if (buf.remaining() < 1) {
|
||
buf = buffer2;
|
||
}
|
||
buf.put((byte) c);
|
||
} else if (c < 0x800) {
|
||
if (buf.remaining() < 2) {
|
||
buf = buffer2;
|
||
}
|
||
buf.put((byte) (0xc0 | (c >> 6)));
|
||
buf.put((byte) (0x80 | (c & 0x3f)));
|
||
} else if (Character.isSurrogate(c)) { // 连取两个
|
||
if (buf.remaining() < 4) {
|
||
buf = buffer2;
|
||
}
|
||
int uc = Character.toCodePoint(c, chs[i + 1]);
|
||
buf.put((byte) (0xf0 | ((uc >> 18))));
|
||
buf.put((byte) (0x80 | ((uc >> 12) & 0x3f)));
|
||
buf.put((byte) (0x80 | ((uc >> 6) & 0x3f)));
|
||
buf.put((byte) (0x80 | (uc & 0x3f)));
|
||
i++;
|
||
} else {
|
||
if (buf.remaining() < 3) {
|
||
buf = buffer2;
|
||
}
|
||
buf.put((byte) (0xe0 | ((c >> 12))));
|
||
buf.put((byte) (0x80 | ((c >> 6) & 0x3f)));
|
||
buf.put((byte) (0x80 | (c & 0x3f)));
|
||
}
|
||
}
|
||
if (buffer2 != null) {
|
||
buffer2.flip();
|
||
}
|
||
return buffer2; // 返回扩展buffer
|
||
}
|
||
|
||
public static String getTypeDescriptor(java.lang.reflect.Type type) {
|
||
if (type == null) {
|
||
return null;
|
||
}
|
||
if (type instanceof Class) {
|
||
Class d = (Class) type;
|
||
final StringBuilder sb = new StringBuilder();
|
||
while (true) {
|
||
if (d.isPrimitive()) {
|
||
char car;
|
||
if (d == Integer.TYPE) {
|
||
car = 'I';
|
||
} else if (d == Void.TYPE) {
|
||
car = 'V';
|
||
} else if (d == Boolean.TYPE) {
|
||
car = 'Z';
|
||
} else if (d == Byte.TYPE) {
|
||
car = 'B';
|
||
} else if (d == Character.TYPE) {
|
||
car = 'C';
|
||
} else if (d == Short.TYPE) {
|
||
car = 'S';
|
||
} else if (d == Double.TYPE) {
|
||
car = 'D';
|
||
} else if (d == Float.TYPE) {
|
||
car = 'F';
|
||
} else /* if (d == Long.TYPE) */ {
|
||
car = 'J';
|
||
}
|
||
return sb.append(car).toString();
|
||
} else if (d.isArray()) {
|
||
sb.append('[');
|
||
d = d.getComponentType();
|
||
} else {
|
||
sb.append('L');
|
||
String name = d.getName();
|
||
int len = name.length();
|
||
for (int i = 0; i < len; ++i) {
|
||
char car = name.charAt(i);
|
||
sb.append(car == '.' ? '/' : car);
|
||
}
|
||
return sb.append(';').toString();
|
||
}
|
||
}
|
||
}
|
||
if (type instanceof ParameterizedType) { // 例如: Map<String, Serializable>
|
||
ParameterizedType pt = (ParameterizedType) type;
|
||
final StringBuilder sb = new StringBuilder();
|
||
String raw = getTypeDescriptor(pt.getRawType());
|
||
sb.append(raw.substring(0, raw.length() - 1)).append('<');
|
||
for (java.lang.reflect.Type item : pt.getActualTypeArguments()) {
|
||
sb.append(getTypeDescriptor(item));
|
||
}
|
||
return sb.append(">;").toString();
|
||
}
|
||
if (type instanceof WildcardType) { // 例如: <? extends Serializable>
|
||
final WildcardType wt = (WildcardType) type;
|
||
final StringBuilder sb = new StringBuilder();
|
||
java.lang.reflect.Type[] us = wt.getUpperBounds();
|
||
java.lang.reflect.Type[] ls = wt.getLowerBounds();
|
||
if (isEmpty(ls)) {
|
||
if (us.length == 1 && us[0] == Object.class) {
|
||
sb.append('*');
|
||
} else {
|
||
for (java.lang.reflect.Type f : us) {
|
||
sb.append('+');
|
||
sb.append(getTypeDescriptor(f));
|
||
}
|
||
}
|
||
}
|
||
for (java.lang.reflect.Type f : ls) {
|
||
sb.append('-');
|
||
sb.append(getTypeDescriptor(f));
|
||
}
|
||
return sb.toString();
|
||
}
|
||
// TypeVariable 不支持
|
||
return null;
|
||
}
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// public static javax.net.ssl.SSLContext getDefaultSSLContext() {
|
||
// return DEFAULTSSL_CONTEXT;
|
||
// }
|
||
//
|
||
// public static javax.net.ssl.HostnameVerifier getDefaultHostnameVerifier() {
|
||
// return defaultVerifier;
|
||
// }
|
||
//
|
||
// public static Socket createDefaultSSLSocket(InetSocketAddress address) throws IOException {
|
||
// return createDefaultSSLSocket(address.getAddress(), address.getPort());
|
||
// }
|
||
//
|
||
// public static Socket createDefaultSSLSocket(InetAddress host, int port) throws IOException {
|
||
// Socket socket = DEFAULTSSL_CONTEXT.getSocketFactory().createSocket(host, port);
|
||
// return socket;
|
||
// }
|
||
//
|
||
public static String postHttpContent(String url) throws IOException {
|
||
return remoteHttpContent("POST", url, 0, null, null).toString(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
public static String postHttpContent(String url, int timeoutMs) throws IOException {
|
||
return remoteHttpContent("POST", url, timeoutMs, null, null).toString(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
public static String postHttpContent(String url, String body) throws IOException {
|
||
return remoteHttpContent("POST", url, 0, null, body).toString(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
public static String postHttpContent(String url, int timeoutMs, String body) throws IOException {
|
||
return remoteHttpContent("POST", url, timeoutMs, null, body).toString(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
public static String postHttpContent(String url, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContent("POST", url, 0, headers, body).toString(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
public static String postHttpContent(String url, int timeoutMs, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContent("POST", url, timeoutMs, headers, body).toString(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
public static String postHttpContent(String url, Charset charset) throws IOException {
|
||
return remoteHttpContent("POST", url, 0, null, null).toString(charset.name());
|
||
}
|
||
|
||
public static String postHttpContent(String url, int timeoutMs, Charset charset) throws IOException {
|
||
return remoteHttpContent("POST", url, timeoutMs, null, null).toString(charset.name());
|
||
}
|
||
|
||
public static String postHttpContent(String url, Charset charset, String body) throws IOException {
|
||
return remoteHttpContent("POST", url, 0, null, body).toString(charset.name());
|
||
}
|
||
|
||
public static String postHttpContent(String url, int timeoutMs, Charset charset, String body) throws IOException {
|
||
return remoteHttpContent("POST", url, timeoutMs, null, body).toString(charset.name());
|
||
}
|
||
|
||
public static String postHttpContent(String url, Charset charset, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContent("POST", url, 0, headers, body).toString(charset.name());
|
||
}
|
||
|
||
public static String postHttpContent(
|
||
String url, int timeoutMs, Charset charset, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContent("POST", url, timeoutMs, headers, body).toString(charset.name());
|
||
}
|
||
|
||
public static byte[] postHttpBytesContent(String url) throws IOException {
|
||
return remoteHttpContent("POST", url, 0, null, null).toByteArray();
|
||
}
|
||
|
||
public static byte[] postHttpBytesContent(String url, int timeoutMs) throws IOException {
|
||
return remoteHttpContent("POST", url, timeoutMs, null, null).toByteArray();
|
||
}
|
||
|
||
public static byte[] postHttpBytesContent(String url, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContent("POST", url, 0, headers, body).toByteArray();
|
||
}
|
||
|
||
public static byte[] postHttpBytesContent(String url, int timeoutMs, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContent("POST", url, timeoutMs, headers, body).toByteArray();
|
||
}
|
||
|
||
public static String getHttpContent(String url) throws IOException {
|
||
return remoteHttpContent("GET", url, 0, null, null).toString(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
public static String getHttpContent(String url, int timeoutMs) throws IOException {
|
||
return remoteHttpContent("GET", url, timeoutMs, null, null).toString(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
public static String getHttpContent(String url, Map<String, Serializable> headers, String body) throws IOException {
|
||
return remoteHttpContent("GET", url, 0, headers, body).toString(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
public static String getHttpContent(String url, int timeoutMs, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContent("GET", url, timeoutMs, headers, body).toString(StandardCharsets.UTF_8);
|
||
}
|
||
|
||
public static String getHttpContent(String url, Charset charset) throws IOException {
|
||
return remoteHttpContent("GET", url, 0, null, null).toString(charset.name());
|
||
}
|
||
|
||
public static String getHttpContent(String url, int timeoutMs, Charset charset) throws IOException {
|
||
return remoteHttpContent("GET", url, timeoutMs, null, null).toString(charset.name());
|
||
}
|
||
|
||
public static String getHttpContent(String url, Charset charset, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContent("GET", url, 0, headers, body).toString(charset.name());
|
||
}
|
||
|
||
public static String getHttpContent(
|
||
String url, int timeoutMs, Charset charset, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContent("GET", url, timeoutMs, headers, body).toString(charset.name());
|
||
}
|
||
|
||
public static byte[] getHttpBytesContent(String url) throws IOException {
|
||
return remoteHttpContent("GET", url, 0, null, null).toByteArray();
|
||
}
|
||
|
||
public static byte[] getHttpBytesContent(String url, int timeoutMs) throws IOException {
|
||
return remoteHttpContent("GET", url, timeoutMs, null, null).toByteArray();
|
||
}
|
||
|
||
public static byte[] getHttpBytesContent(String url, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContent("GET", url, 0, headers, body).toByteArray();
|
||
}
|
||
|
||
public static byte[] getHttpBytesContent(String url, int timeoutMs, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContent("GET", url, timeoutMs, headers, body).toByteArray();
|
||
}
|
||
|
||
public static String remoteHttpContent(HttpClient client, String method, String url, Charset charset)
|
||
throws IOException {
|
||
return remoteHttpContentAsync(client, method, url, 0, null, null)
|
||
.thenApply(out -> out.toString(charset == null ? StandardCharsets.UTF_8 : charset))
|
||
.join();
|
||
}
|
||
|
||
public static String remoteHttpContent(HttpClient client, String method, String url, int timeoutMs, Charset charset)
|
||
throws IOException {
|
||
return remoteHttpContentAsync(client, method, url, timeoutMs, null, null)
|
||
.thenApply(out -> out.toString(charset == null ? StandardCharsets.UTF_8 : charset))
|
||
.join();
|
||
}
|
||
|
||
public static String remoteHttpContent(
|
||
HttpClient client, String method, String url, Charset charset, Map<String, Serializable> headers)
|
||
throws IOException {
|
||
return remoteHttpContentAsync(client, method, url, 0, headers, null)
|
||
.thenApply(out -> out.toString(charset == null ? StandardCharsets.UTF_8 : charset))
|
||
.join();
|
||
}
|
||
|
||
public static String remoteHttpContent(
|
||
HttpClient client,
|
||
String method,
|
||
String url,
|
||
Charset charset,
|
||
Map<String, Serializable> headers,
|
||
String body)
|
||
throws IOException {
|
||
return remoteHttpContentAsync(client, method, url, 0, headers, body)
|
||
.thenApply(out -> out.toString(charset == null ? StandardCharsets.UTF_8 : charset))
|
||
.join();
|
||
}
|
||
|
||
public static String remoteHttpContent(
|
||
HttpClient client,
|
||
String method,
|
||
String url,
|
||
int timeoutMs,
|
||
Charset charset,
|
||
Map<String, Serializable> headers)
|
||
throws IOException {
|
||
return remoteHttpContentAsync(client, method, url, timeoutMs, headers, null)
|
||
.thenApply(out -> out.toString(charset == null ? StandardCharsets.UTF_8 : charset))
|
||
.join();
|
||
}
|
||
|
||
public static String remoteHttpContent(
|
||
HttpClient client,
|
||
String method,
|
||
String url,
|
||
int timeoutMs,
|
||
Charset charset,
|
||
Map<String, Serializable> headers,
|
||
String body)
|
||
throws IOException {
|
||
return remoteHttpContentAsync(client, method, url, timeoutMs, headers, body)
|
||
.thenApply(out -> out.toString(charset == null ? StandardCharsets.UTF_8 : charset))
|
||
.join();
|
||
}
|
||
|
||
public static byte[] remoteHttpBytesContent(
|
||
HttpClient client,
|
||
String method,
|
||
String url,
|
||
Charset charset,
|
||
Map<String, Serializable> headers,
|
||
String body)
|
||
throws IOException {
|
||
return remoteHttpContentAsync(client, method, url, 0, headers, body)
|
||
.thenApply(out -> out.toByteArray())
|
||
.join();
|
||
}
|
||
|
||
public static byte[] remoteHttpBytesContent(
|
||
HttpClient client,
|
||
String method,
|
||
String url,
|
||
int timeoutMs,
|
||
Charset charset,
|
||
Map<String, Serializable> headers)
|
||
throws IOException {
|
||
return remoteHttpContentAsync(client, method, url, timeoutMs, headers, null)
|
||
.thenApply(out -> out.toByteArray())
|
||
.join();
|
||
}
|
||
|
||
public static byte[] remoteHttpBytesContent(
|
||
HttpClient client,
|
||
String method,
|
||
String url,
|
||
int timeoutMs,
|
||
Charset charset,
|
||
Map<String, Serializable> headers,
|
||
String body)
|
||
throws IOException {
|
||
return remoteHttpContentAsync(client, method, url, timeoutMs, headers, body)
|
||
.thenApply(out -> out.toByteArray())
|
||
.join();
|
||
}
|
||
|
||
public static ByteArrayOutputStream remoteHttpContent(
|
||
String method, String url, Map<String, Serializable> headers, String body) throws IOException {
|
||
return remoteHttpContent(method, url, 0, headers, body);
|
||
}
|
||
|
||
public static ByteArrayOutputStream remoteHttpContent(
|
||
String method, String url, int timeoutMs, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContentAsync(method, url, timeoutMs, headers, body).join();
|
||
}
|
||
|
||
public static ByteArrayOutputStream remoteHttpContent(
|
||
HttpClient client, String method, String url, int timeoutMs, Map<String, Serializable> headers, String body)
|
||
throws IOException {
|
||
return remoteHttpContentAsync(client, method, url, timeoutMs, headers, body)
|
||
.join();
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(String url) {
|
||
return remoteHttpContentAsync("POST", url, 0, null, null)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(String url, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, 0, null, null, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(String url, int timeoutMs) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, null, null)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, int timeoutMs, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, null, null, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(String url, String body) {
|
||
return remoteHttpContentAsync("POST", url, 0, null, body)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, String body, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, 0, null, body, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(String url, int timeoutMs, String body) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, null, body)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, int timeoutMs, String body, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, null, body, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("POST", url, 0, headers, body)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, Map<String, Serializable> headers, String body, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, 0, headers, body, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, int timeoutMs, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, headers, body)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url,
|
||
int timeoutMs,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, headers, body, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(String url, Charset charset) {
|
||
return remoteHttpContentAsync("POST", url, 0, null, null).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, Charset charset, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, 0, null, null, respHeaders).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(String url, int timeoutMs, Charset charset) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, null, null).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, int timeoutMs, Charset charset, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, null, null, respHeaders)
|
||
.thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(String url, Charset charset, String body) {
|
||
return remoteHttpContentAsync("POST", url, 0, null, body).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, Charset charset, String body, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, 0, null, body, respHeaders).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
HttpClient client, String url, Charset charset, String body) {
|
||
return remoteHttpContentAsync(client, "POST", url, 0, null, body).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
HttpClient client, String url, Charset charset, String body, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync(client, "POST", url, 0, null, body, respHeaders)
|
||
.thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
HttpClient client, String url, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync(client, "POST", url, 0, headers, body)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
HttpClient client,
|
||
String url,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync(client, "POST", url, 0, headers, body, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
HttpClient client, String url, Charset charset, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync(client, "POST", url, 0, headers, body).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
HttpClient client,
|
||
String url,
|
||
Charset charset,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync(client, "POST", url, 0, headers, body, respHeaders)
|
||
.thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, int timeoutMs, Charset charset, String body) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, null, body).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, int timeoutMs, Charset charset, String body, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, null, body, respHeaders)
|
||
.thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, Charset charset, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("POST", url, 0, headers, body).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url,
|
||
Charset charset,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, 0, headers, body, respHeaders)
|
||
.thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url, int timeoutMs, Charset charset, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, headers, body).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> postHttpContentAsync(
|
||
String url,
|
||
int timeoutMs,
|
||
Charset charset,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, headers, body, respHeaders)
|
||
.thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> postHttpBytesContentAsync(String url) {
|
||
return remoteHttpContentAsync("POST", url, 0, null, null).thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> postHttpBytesContentAsync(
|
||
String url, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, 0, null, null, respHeaders).thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> postHttpBytesContentAsync(String url, int timeoutMs) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, null, null).thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> postHttpBytesContentAsync(
|
||
String url, int timeoutMs, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, null, null, respHeaders)
|
||
.thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> postHttpBytesContentAsync(
|
||
String url, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("POST", url, 0, headers, body).thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> postHttpBytesContentAsync(
|
||
String url, Map<String, Serializable> headers, String body, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, 0, headers, body, respHeaders)
|
||
.thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> postHttpBytesContentAsync(
|
||
String url, int timeoutMs, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, headers, body).thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> postHttpBytesContentAsync(
|
||
String url,
|
||
int timeoutMs,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("POST", url, timeoutMs, headers, body, respHeaders)
|
||
.thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(String url) {
|
||
return remoteHttpContentAsync("GET", url, 0, null, null).thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(String url, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, 0, null, null, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(String url, int timeoutMs) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, null, null)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
String url, int timeoutMs, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, null, null, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
String url, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("GET", url, 0, headers, body)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
String url, Map<String, Serializable> headers, String body, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, 0, headers, body, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
String url, int timeoutMs, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, headers, body)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
String url,
|
||
int timeoutMs,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, headers, body, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(String url, Charset charset) {
|
||
return remoteHttpContentAsync("GET", url, 0, null, null).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
String url, Charset charset, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, 0, null, null, respHeaders).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(String url, int timeoutMs, Charset charset) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, null, null).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
String url, int timeoutMs, Charset charset, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, null, null, respHeaders)
|
||
.thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
String url, Charset charset, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("GET", url, 0, headers, body).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
String url,
|
||
Charset charset,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, 0, headers, body, respHeaders)
|
||
.thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
String url, int timeoutMs, Charset charset, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, headers, body).thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
String url,
|
||
int timeoutMs,
|
||
Charset charset,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, headers, body, respHeaders)
|
||
.thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
java.net.http.HttpClient client, String url, String body, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync(client, "GET", url, 0, null, body, respHeaders)
|
||
.thenApply(out -> out.toString(StandardCharsets.UTF_8));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
java.net.http.HttpClient client,
|
||
String url,
|
||
Charset charset,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync(client, "GET", url, 0, null, body, respHeaders)
|
||
.thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<String> getHttpContentAsync(
|
||
java.net.http.HttpClient client,
|
||
String url,
|
||
Charset charset,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync(client, "GET", url, 0, headers, body, respHeaders)
|
||
.thenApply(out -> out.toString(charset));
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> getHttpBytesContentAsync(String url) {
|
||
return remoteHttpContentAsync("GET", url, 0, null, null).thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> getHttpBytesContentAsync(
|
||
String url, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, 0, null, null, respHeaders).thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> getHttpBytesContentAsync(String url, int timeoutMs) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, null, null).thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> getHttpBytesContentAsync(
|
||
String url, int timeoutMs, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, null, null, respHeaders)
|
||
.thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> getHttpBytesContentAsync(
|
||
String url, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("GET", url, 0, headers, body).thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> getHttpBytesContentAsync(
|
||
String url, Map<String, Serializable> headers, String body, Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, 0, headers, body, respHeaders).thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> getHttpBytesContentAsync(
|
||
String url, int timeoutMs, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, headers, body).thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> getHttpBytesContentAsync(
|
||
String url,
|
||
int timeoutMs,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync("GET", url, timeoutMs, headers, body, respHeaders)
|
||
.thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<byte[]> getHttpBytesContentAsync(
|
||
java.net.http.HttpClient client,
|
||
String url,
|
||
int timeoutMs,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync(client, "GET", url, timeoutMs, headers, body, respHeaders)
|
||
.thenApply(out -> out.toByteArray());
|
||
}
|
||
|
||
public static CompletableFuture<ByteArrayOutputStream> remoteHttpContentAsync(
|
||
String method, String url, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync(method, url, 0, headers, body);
|
||
}
|
||
|
||
public static CompletableFuture<ByteArrayOutputStream> remoteHttpContentAsync(
|
||
String method,
|
||
String url,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync(method, url, 0, headers, body, respHeaders);
|
||
}
|
||
|
||
public static CompletableFuture<ByteArrayOutputStream> remoteHttpContentAsync(
|
||
String method, String url, int timeoutMs, Map<String, Serializable> headers, String body) {
|
||
return remoteHttpContentAsync(httpClient, method, url, timeoutMs, headers, body);
|
||
}
|
||
|
||
public static CompletableFuture<ByteArrayOutputStream> remoteHttpContentAsync(
|
||
String method,
|
||
String url,
|
||
int timeoutMs,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
return remoteHttpContentAsync(httpClient, method, url, timeoutMs, headers, body, respHeaders);
|
||
}
|
||
|
||
public static CompletableFuture<ByteArrayOutputStream> remoteHttpContentAsync(
|
||
java.net.http.HttpClient client,
|
||
String method,
|
||
String url,
|
||
int timeoutMs,
|
||
Map<String, Serializable> headers,
|
||
String body) {
|
||
return remoteHttpContentAsync(client, method, url, timeoutMs, headers, body, null);
|
||
}
|
||
|
||
public static CompletableFuture<ByteArrayOutputStream> remoteHttpContentAsync(
|
||
java.net.http.HttpClient client,
|
||
String method,
|
||
String url,
|
||
int timeoutMs,
|
||
Map<String, Serializable> headers,
|
||
String body,
|
||
Map<String, Serializable> respHeaders) {
|
||
java.net.http.HttpRequest.Builder builder = java.net.http.HttpRequest.newBuilder()
|
||
.uri(URI.create(url))
|
||
.timeout(Duration.ofMillis(timeoutMs > 0 ? timeoutMs : 6000))
|
||
.method(
|
||
method,
|
||
body == null
|
||
? java.net.http.HttpRequest.BodyPublishers.noBody()
|
||
: java.net.http.HttpRequest.BodyPublishers.ofString(body));
|
||
if (headers != null) {
|
||
headers.forEach((n, v) -> {
|
||
if (v instanceof Collection) {
|
||
for (Object val : (Collection) v) {
|
||
builder.header(n, val.toString());
|
||
}
|
||
} else {
|
||
builder.header(n, v.toString());
|
||
}
|
||
});
|
||
}
|
||
java.net.http.HttpClient c = client == null ? httpClient : client;
|
||
if (c == null) {
|
||
clientLock.lock();
|
||
try {
|
||
if (httpClient == null) {
|
||
httpClient = java.net.http.HttpClient.newHttpClient();
|
||
}
|
||
} finally {
|
||
clientLock.unlock();
|
||
}
|
||
c = httpClient;
|
||
}
|
||
return c.sendAsync(builder.build(), java.net.http.HttpResponse.BodyHandlers.ofByteArray())
|
||
.thenCompose((java.net.http.HttpResponse<byte[]> resp) -> {
|
||
final int rs = resp.statusCode();
|
||
if (rs == 301 || rs == 302) {
|
||
Optional<String> opt = resp.headers().firstValue("Location");
|
||
if (opt.isPresent()) {
|
||
return remoteHttpContentAsync(client, method, opt.get(), timeoutMs, headers, body);
|
||
} else {
|
||
return CompletableFuture.failedFuture(
|
||
new IOException(url + " httpcode = " + rs + ", but not found Localtion"));
|
||
}
|
||
}
|
||
byte[] result = resp.body();
|
||
if (rs == 200 || result != null) {
|
||
if (respHeaders != null) {
|
||
resp.headers().map().forEach((k, l) -> {
|
||
if (!l.isEmpty()) {
|
||
respHeaders.put(k, l.get(0));
|
||
}
|
||
});
|
||
}
|
||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||
if (result != null) {
|
||
if ("gzip"
|
||
.equalsIgnoreCase(resp.headers()
|
||
.firstValue("content-encoding")
|
||
.orElse(null))) {
|
||
try {
|
||
GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(result));
|
||
in.transferTo(out);
|
||
} catch (IOException e) {
|
||
return CompletableFuture.failedFuture(e);
|
||
}
|
||
} else {
|
||
out.writeBytes(result);
|
||
}
|
||
}
|
||
return CompletableFuture.completedFuture(out);
|
||
}
|
||
return CompletableFuture.failedFuture(new RetcodeException(rs, url + " httpcode = " + rs));
|
||
});
|
||
}
|
||
//
|
||
// public static ByteArrayOutputStream remoteHttpContent(SSLContext ctx, String method, String url, int
|
||
// timeoutMs, Map<String, Serializable> headers, String body) throws IOException {
|
||
// HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||
// boolean opening = true;
|
||
// try {
|
||
// conn.setConnectTimeout(timeoutMs > 0 ? timeoutMs : 30000);
|
||
// conn.setReadTimeout(timeoutMs > 0 ? timeoutMs : 30000);
|
||
// if (conn instanceof HttpsURLConnection) {
|
||
// HttpsURLConnection httpsconn = ((HttpsURLConnection) conn);
|
||
// httpsconn.setSSLSocketFactory((ctx == null ? DEFAULTSSL_CONTEXT : ctx).getSocketFactory());
|
||
// httpsconn.setHostnameVerifier(defaultVerifier);
|
||
// }
|
||
// conn.setRequestMethod(method);
|
||
// if (headers != null) {
|
||
// for (Map.Entry<String, String> en : headers.entrySet()) {
|
||
// conn.setRequestProperty(en.getKey(), en.getValue());
|
||
// }
|
||
// }
|
||
// if (body != null && !body.isEmpty()) { //conn.getOutputStream()会将GET强制变成POST
|
||
// conn.setDoInput(true);
|
||
// conn.setDoOutput(true);
|
||
// conn.getOutputStream().write(body.getBytes(UTF_8));
|
||
// }
|
||
// conn.connect();
|
||
// int rs = conn.getResponseCode();
|
||
// if (rs == 301 || rs == 302) {
|
||
// String newurl = conn.getHeaderField("Location");
|
||
// conn.disconnect();
|
||
// opening = false;
|
||
// return remoteHttpContent(ctx, method, newurl, timeoutMs, headers, body);
|
||
// }
|
||
// InputStream in = (rs < 400 || rs == 404) && rs != 405 ? conn.getInputStream() : conn.getErrorStream();
|
||
// if ("gzip".equalsIgnoreCase(conn.getContentEncoding())) in = new GZIPInputStream(in);
|
||
// ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
||
// byte[] bytes = new byte[1024];
|
||
// int pos;
|
||
// while ((pos = in.read(bytes)) != -1) {
|
||
// out.write(bytes, 0, pos);
|
||
// }
|
||
// in.close();
|
||
// return out;
|
||
// } finally {
|
||
// if (opening) conn.disconnect();
|
||
// }
|
||
// }
|
||
|
||
public static String read(InputStream in) throws IOException {
|
||
return read(in, StandardCharsets.UTF_8, false);
|
||
}
|
||
|
||
public static String readThenClose(InputStream in) throws IOException {
|
||
return read(in, StandardCharsets.UTF_8, true);
|
||
}
|
||
|
||
public static String read(InputStream in, String charsetName) throws IOException {
|
||
return read(in, Charset.forName(charsetName), false);
|
||
}
|
||
|
||
public static String read(InputStream in, Charset charset) throws IOException {
|
||
return read(in, charset, false);
|
||
}
|
||
|
||
private static String read(InputStream in, Charset charset, boolean close) throws IOException {
|
||
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
||
byte[] bytes = new byte[1024];
|
||
int pos;
|
||
while ((pos = in.read(bytes)) != -1) {
|
||
out.write(bytes, 0, pos);
|
||
}
|
||
if (close) {
|
||
in.close();
|
||
}
|
||
return charset == null ? out.toString() : out.toString(charset);
|
||
}
|
||
|
||
public static ByteArrayOutputStream readStream(InputStream in) throws IOException {
|
||
return readStream(in, false);
|
||
}
|
||
|
||
public static ByteArrayOutputStream readStreamThenClose(InputStream in) throws IOException {
|
||
return readStream(in, true);
|
||
}
|
||
|
||
private static ByteArrayOutputStream readStream(InputStream in, boolean close) throws IOException {
|
||
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
||
byte[] bytes = new byte[1024];
|
||
int pos;
|
||
while ((pos = in.read(bytes)) != -1) {
|
||
out.write(bytes, 0, pos);
|
||
}
|
||
if (close) {
|
||
in.close();
|
||
}
|
||
return out;
|
||
}
|
||
|
||
public static byte[] readBytes(File file) throws IOException {
|
||
return readBytesThenClose(new FileInputStream(file));
|
||
}
|
||
|
||
public static byte[] readBytes(InputStream in) throws IOException {
|
||
return readStream(in).toByteArray();
|
||
}
|
||
|
||
public static byte[] readBytesThenClose(InputStream in) throws IOException {
|
||
return readStreamThenClose(in).toByteArray();
|
||
}
|
||
}
|