diff --git a/arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/util/StringUtil.java b/arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/util/StringUtil.java index 5d67425a9..89b6af41b 100644 --- a/arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/util/StringUtil.java +++ b/arex-agent-bootstrap/src/main/java/io/arex/agent/bootstrap/util/StringUtil.java @@ -550,4 +550,17 @@ public static Integer getFirstNumeric(String s) { public static boolean isNullWord(String str) { return equals(str, "null") || equals(str, "NULL"); } + + public static int countMatches(final String str, final String sub) { + if (isEmpty(str) || isEmpty(sub)) { + return 0; + } + int count = 0; + int idx = 0; + while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) { + count++; + idx += sub.length(); + } + return count; + } } diff --git a/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/model/ArexConstants.java b/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/model/ArexConstants.java index 4fff6f618..2a67c0aa2 100644 --- a/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/model/ArexConstants.java +++ b/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/model/ArexConstants.java @@ -31,6 +31,9 @@ private ArexConstants() {} public static final String REPLAY_ORIGINAL_MOCKER = "arex-replay-original-mocker"; public static final String AREX_EXTENSION_ATTRIBUTE = "arex-extension-attribute"; public static final String GSON_SERIALIZER = "gson"; + public static final String GSON_REQUEST_SERIALIZER = "gson-request"; + public static final String JACKSON_SERIALIZER = "jackson"; + public static final String JACKSON_REQUEST_SERIALIZER = "jackson-request"; public static final String CONFIG_DEPENDENCY = "arex_replay_prepare_dependency"; public static final String PREFIX = "arex-"; public static final String CONFIG_VERSION = "configBatchNo"; diff --git a/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/serializer/Serializer.java b/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/serializer/Serializer.java index 778716a23..b59bd1c0e 100644 --- a/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/serializer/Serializer.java +++ b/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/serializer/Serializer.java @@ -122,6 +122,19 @@ public static String serialize(Object object, String serializer) { } } +// public static String serializeRequest(Object object) { +// return serializeRequest(object, ArexConstants.JACKSON_REQUEST_SERIALIZER); +// } +// +// public static String serializeRequest(Object object, String serializer) { +// try { +// return serializeWithException(object, serializer); +// } catch (Throwable ex) { +// LogManager.warn("serializeRequest", StringUtil.format("can not serialize object: %s, cause: %s", TypeUtil.errorSerializeToString(object), ex.toString())); +// return null; +// } +// } + /** * Deserialize by Class * diff --git a/arex-instrumentation-foundation/pom.xml b/arex-instrumentation-foundation/pom.xml index 0c212f70f..1fc1b551a 100644 --- a/arex-instrumentation-foundation/pom.xml +++ b/arex-instrumentation-foundation/pom.xml @@ -84,6 +84,16 @@ 2.6 test + + org.openjdk.jmh + jmh-core + 1.23 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.23 + diff --git a/arex-instrumentation-foundation/src/main/java/io/arex/foundation/serializer/GsonRequestSerializer.java b/arex-instrumentation-foundation/src/main/java/io/arex/foundation/serializer/GsonRequestSerializer.java new file mode 100644 index 000000000..bffac88e5 --- /dev/null +++ b/arex-instrumentation-foundation/src/main/java/io/arex/foundation/serializer/GsonRequestSerializer.java @@ -0,0 +1,104 @@ +package io.arex.foundation.serializer; + +import com.google.auto.service.AutoService; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import io.arex.foundation.serializer.custom.ProtobufAdapterFactory; +import io.arex.foundation.serializer.custom.SerializerExclusionStrategy; +import io.arex.foundation.serializer.custom.StringAdapter; +import io.arex.foundation.serializer.custom.time.adapter.CalendarAdapter; +import io.arex.foundation.serializer.custom.time.adapter.ClassAdapter; +import io.arex.foundation.serializer.custom.time.adapter.DateAdapter; +import io.arex.foundation.serializer.custom.time.adapter.DateTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.InstantAdapter; +import io.arex.foundation.serializer.custom.time.adapter.JodaLocalDateAdapter; +import io.arex.foundation.serializer.custom.time.adapter.JodaLocalDateTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.JodaLocalTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.LocalDateAdapter; +import io.arex.foundation.serializer.custom.time.adapter.LocalDateTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.LocalTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.OffsetDateTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.TimeZoneAdapter; +import io.arex.foundation.serializer.custom.time.adapter.XMLGregorianCalendarAdapter; +import io.arex.inst.runtime.serializer.StringSerializable; +import org.joda.time.DateTime; + +import javax.xml.datatype.XMLGregorianCalendar; +import java.lang.reflect.Type; +import java.sql.Time; +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +@AutoService(StringSerializable.class) +public class GsonRequestSerializer implements StringSerializable{ + + public static GsonRequestSerializer INSTANCE = new GsonRequestSerializer(); + private final Gson serializer; + + public GsonRequestSerializer() { + this.serializer = new GsonBuilder() + .registerTypeAdapter(DateTime.class, new DateTimeAdapter.GsonSerializer(true)) + .registerTypeAdapter(org.joda.time.LocalDateTime.class, new JodaLocalDateTimeAdapter.GsonSerializer(true)) + .registerTypeAdapter(org.joda.time.LocalDate.class, new JodaLocalDateAdapter.GsonSerializer()) + .registerTypeAdapter(org.joda.time.LocalTime.class, new JodaLocalTimeAdapter.GsonSerializer(true)) + .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter.GsonSerializer(true)) + .registerTypeAdapter(LocalDate.class, new LocalDateAdapter.GsonSerializer()) + .registerTypeAdapter(LocalTime.class, new LocalTimeAdapter.GsonSerializer(true)) + .registerTypeAdapter(Calendar.class, new CalendarAdapter.GsonSerializer(true)) + .registerTypeAdapter(GregorianCalendar.class, new CalendarAdapter.GsonSerializer(true)) + .registerTypeAdapter(XMLGregorianCalendar.class, new XMLGregorianCalendarAdapter.GsonSerializer(true)) + .registerTypeAdapter(Timestamp.class, new DateAdapter.GsonSerializer(true)) + .registerTypeAdapter(Date.class, new DateAdapter.GsonSerializer(true)) + .registerTypeAdapter(java.sql.Date.class, new DateAdapter.GsonSerializer(true)) + .registerTypeAdapter(Time.class, new DateAdapter.GsonSerializer(true)) + .registerTypeAdapter(Instant.class, new InstantAdapter.GsonSerializer(true)) + .registerTypeAdapter(Class.class, new ClassAdapter.GsonSerializer()) + .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeAdapter.GsonSerializer(true)) + .registerTypeAdapter(TimeZone.class, new TimeZoneAdapter.GsonSerializer()) + .registerTypeAdapter(String.class, new StringAdapter.GsonSerializer()) + .registerTypeAdapterFactory(new ProtobufAdapterFactory()) + .enableComplexMapKeySerialization() + .setExclusionStrategies(new SerializerExclusionStrategy.GsonExclusion()) + .disableHtmlEscaping() + .create(); + } + + @Override + public String name() { + return "gson-request"; + } + + @Override + public String serialize(Object object) throws Throwable { + if (object == null) { + return null; + } + return serializer.toJson(object); + } + + @Override + public T deserialize(String value, Class clazz) throws Throwable { + // request serializer not need deserialize + return null; + } + + @Override + public T deserialize(String value, Type type) throws Throwable { + // request serializer not need deserialize + return null; + } + + @Override + public StringSerializable reCreateSerializer() { + INSTANCE = new GsonRequestSerializer(); + return INSTANCE; + } +} diff --git a/arex-instrumentation-foundation/src/main/java/io/arex/foundation/serializer/GsonSerializer.java b/arex-instrumentation-foundation/src/main/java/io/arex/foundation/serializer/GsonSerializer.java index c74d68113..7a70d8139 100644 --- a/arex-instrumentation-foundation/src/main/java/io/arex/foundation/serializer/GsonSerializer.java +++ b/arex-instrumentation-foundation/src/main/java/io/arex/foundation/serializer/GsonSerializer.java @@ -3,8 +3,6 @@ import com.google.auto.service.AutoService; import com.google.common.collect.Range; -import io.arex.agent.thirdparty.util.time.DateFormatUtils; -import io.arex.foundation.serializer.JacksonSerializer.DateFormatParser; import io.arex.foundation.serializer.custom.FastUtilAdapterFactory; import io.arex.foundation.serializer.custom.GuavaRangeSerializer; import io.arex.agent.bootstrap.util.StringUtil; @@ -13,23 +11,40 @@ import io.arex.foundation.serializer.custom.NumberStrategy; import io.arex.foundation.serializer.custom.ProtobufAdapterFactory; +import io.arex.foundation.serializer.custom.SerializerExclusionStrategy; +import io.arex.foundation.serializer.custom.StringAdapter; +import io.arex.foundation.serializer.custom.time.adapter.CalendarAdapter; +import io.arex.foundation.serializer.custom.time.adapter.ClassAdapter; +import io.arex.foundation.serializer.custom.time.adapter.DateAdapter; +import io.arex.foundation.serializer.custom.time.adapter.DateTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.GregorianCalendarAdapter; +import io.arex.foundation.serializer.custom.time.adapter.InstantAdapter; +import io.arex.foundation.serializer.custom.time.adapter.JodaLocalDateAdapter; +import io.arex.foundation.serializer.custom.time.adapter.JodaLocalDateTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.JodaLocalTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.LocalDateAdapter; +import io.arex.foundation.serializer.custom.time.adapter.LocalDateTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.LocalTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.OffsetDateTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.SqlDateAdapter; +import io.arex.foundation.serializer.custom.time.adapter.SqlTimeAdapter; +import io.arex.foundation.serializer.custom.time.adapter.TimeZoneAdapter; +import io.arex.foundation.serializer.custom.time.adapter.TimestampAdapter; +import io.arex.foundation.serializer.custom.time.adapter.XMLGregorianCalendarAdapter; import io.arex.inst.runtime.log.LogManager; import io.arex.inst.runtime.serializer.StringSerializable; import io.arex.inst.runtime.util.TypeUtil; + import java.sql.Time; import java.time.Instant; import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; import java.util.Map.Entry; import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.joda.time.format.DateTimeFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.*; -import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; import java.lang.reflect.Type; import java.sql.Timestamp; @@ -42,133 +57,6 @@ public class GsonSerializer implements StringSerializable { private static final Logger LOGGER = LoggerFactory.getLogger(GsonSerializer.class); - private static final JsonSerializer DATE_TIME_JSON_SERIALIZER = - ((src, typeOfSrc, context) -> new JsonPrimitive(src.toString(JacksonSerializer.DatePatternConstants.SIMPLE_DATE_FORMAT_WITH_TIMEZONE_DATETIME))); - private static final JsonDeserializer DATE_TIME_JSON_DESERIALIZER = - (json, type, context) -> { - TimeZone timeZone = JacksonSerializer.TimezoneParser.INSTANCE.parse(json.getAsString()); - DateTimeZone dateTimeZone = DateTimeZone.forTimeZone(timeZone); - Date date = DateFormatParser.INSTANCE.parseDate(json.getAsString(), timeZone); - if (date == null) { - return null; - } - return new DateTime(date.getTime()).withZone(dateTimeZone); - }; - - private static final JsonSerializer JODA_LOCAL_DATE_TIME_JSON_SERIALIZER = - (src, typeOfSrc, context) -> new JsonPrimitive(src.toString(JacksonSerializer.DatePatternConstants.SIMPLE_DATE_FORMAT_MILLIS)); - private static final JsonDeserializer JODA_LOCAL_DATE_TIME_JSON_DESERIALIZER = (json, type, context) -> - org.joda.time.LocalDateTime.parse(json.getAsString(), DateTimeFormat.forPattern(JacksonSerializer.DatePatternConstants.SIMPLE_DATE_FORMAT_MILLIS)); - - private static final JsonSerializer JODA_LOCAL_DATE_JSON_SERIALIZER = - (src, typeOfSrc, context) -> new JsonPrimitive(src.toString(JacksonSerializer.DatePatternConstants.SHORT_DATE_FORMAT)); - private static final JsonDeserializer JODA_LOCAL_DATE_JSON_DESERIALIZER = (json, type, context) -> - org.joda.time.LocalDate.parse(json.getAsString(), DateTimeFormat.forPattern(JacksonSerializer.DatePatternConstants.SHORT_DATE_FORMAT)); - - private static final JsonSerializer JODA_LOCAL_TIME_JSON_SERIALIZER = - (src, typeOfSrc, context) -> new JsonPrimitive(src.toString(JacksonSerializer.DatePatternConstants.SHORT_TIME_FORMAT_MILLISECOND)); - private static final JsonDeserializer JODA_LOCAL_TIME_JSON_DESERIALIZER = (json, type, context) -> - org.joda.time.LocalTime.parse(json.getAsString(), DateTimeFormat.forPattern(JacksonSerializer.DatePatternConstants.SHORT_TIME_FORMAT_MILLISECOND)); - - private static final JsonSerializer LOCAL_DATE_TIME_JSON_SERIALIZER = - ((src, typeOfSrc, context) -> new JsonPrimitive(src.format(DateTimeFormatter.ofPattern(JacksonSerializer.DatePatternConstants.localDateTimeFormat)))); - private static final JsonDeserializer LOCAL_DATE_TIME_JSON_DESERIALIZER = (json, type, context) -> - LocalDateTime.parse(json.getAsString(), JacksonSerializer.DateFormatParser.INSTANCE.getFormatter(JacksonSerializer.DatePatternConstants.localDateTimeFormat)); - private static final JsonSerializer LOCAL_DATE_JSON_SERIALIZER = - ((src, typeOfSrc, context) -> new JsonPrimitive(src.format(DateTimeFormatter.ofPattern(JacksonSerializer.DatePatternConstants.SHORT_DATE_FORMAT)))); - - private static final JsonDeserializer LOCAL_DATE_JSON_DESERIALIZER = (json, type, context) -> - LocalDate.parse(json.getAsString(), JacksonSerializer.DateFormatParser.INSTANCE.getFormatter(JacksonSerializer.DatePatternConstants.SHORT_DATE_FORMAT)); - - private static final JsonSerializer LOCAL_TIME_JSON_SERIALIZER = - ((src, typeOfSrc, context) -> new JsonPrimitive(src.format(DateTimeFormatter.ofPattern(JacksonSerializer.DatePatternConstants.localTimeFormat)))); - - private static final JsonDeserializer LOCAL_TIME_JSON_DESERIALIZER = (json, type, context) -> - LocalTime.parse(json.getAsString(), JacksonSerializer.DateFormatParser.INSTANCE.getFormatter(JacksonSerializer.DatePatternConstants.localTimeFormat)); - - private static final JsonSerializer CALENDAR_JSON_SERIALIZER = - (((src, typeOfSrc, context) -> new JsonPrimitive( - DateFormatUtils.format(src, JacksonSerializer.DatePatternConstants.SIMPLE_DATE_FORMAT_WITH_TIMEZONE, src.getTimeZone())))); - - private static final JsonDeserializer CALENDAR_JSON_DESERIALIZER = (json, type, context) -> - JacksonSerializer.DateFormatParser.INSTANCE.parseCalendar(json.getAsString()); - - private static final JsonSerializer GREGORIAN_CALENDAR_JSON_SERIALIZER = - (((src, typeOfSrc, context) -> new JsonPrimitive(DateFormatUtils.format(src, JacksonSerializer.DatePatternConstants.SIMPLE_DATE_FORMAT_WITH_TIMEZONE, src.getTimeZone())))); - - private static final JsonDeserializer GREGORIAN_CALENDAR_JSON_DESERIALIZER = (json, type, context) -> - JacksonSerializer.DateFormatParser.INSTANCE.parseGregorianCalendar(json.getAsString()); - - private static final JsonSerializer XML_GREGORIAN_CALENDAR_JSON_SERIALIZER = - (((src, typeOfSrc, context) -> { - GregorianCalendar calendar = src.toGregorianCalendar(); - return new JsonPrimitive(DateFormatUtils.format(calendar, JacksonSerializer.DatePatternConstants.SIMPLE_DATE_FORMAT_WITH_TIMEZONE, calendar.getTimeZone())); - })); - - private static final JsonDeserializer XML_GREGORIAN_CALENDAR_JSON_DESERIALIZER = - (json, type, context) -> { - GregorianCalendar calendar = JacksonSerializer.DateFormatParser.INSTANCE.parseGregorianCalendar(json.getAsString()); - XMLGregorianCalendar xmlGregorianCalendar = null; - try { - xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar); - } catch (Exception ex) { - LOGGER.warn("XMLGregorianCalendar.deserialize", ex); - } - return xmlGregorianCalendar; - }; - - private static final JsonSerializer TIMESTAMP_JSON_SERIALIZER = - (((src, typeOfSrc, context) -> new JsonPrimitive(DateFormatUtils.format(src, JacksonSerializer.DatePatternConstants.SIMPLE_DATE_FORMAT_MILLIS)))); - - private static final JsonDeserializer TIMESTAMP_JSON_DESERIALIZER = (json, typeOfT, context) -> - Optional.ofNullable(JacksonSerializer.DateFormatParser.INSTANCE.parseDate(json.getAsString())) - .map(date -> new Timestamp(date.getTime())).orElse(new Timestamp(System.currentTimeMillis())); - - private static final JsonSerializer DATE_JSON_SERIALIZER = - (((src, typeOfSrc, context) -> new JsonPrimitive(DateFormatUtils.format(src, JacksonSerializer.DatePatternConstants.SIMPLE_DATE_FORMAT_MILLIS)))); - private static final JsonDeserializer DATE_JSON_DESERIALIZER = (json, type, context) -> - DateFormatParser.INSTANCE.parseDate(json.getAsString()); - - private static final JsonSerializer SQL_DATE_JSON_SERIALIZER = - (((src, typeOfSrc, context) -> new JsonPrimitive(DateFormatUtils.format(src, JacksonSerializer.DatePatternConstants.SIMPLE_DATE_FORMAT_MILLIS)))); - - private static final JsonDeserializer SQL_DATE_JSON_DESERIALIZER = (json, type, context) ->{ - Date date = DateFormatParser.INSTANCE.parseDate(json.getAsString()); - return new java.sql.Date(date.getTime()); - }; - - private static final JsonSerializer