Skip to content

Instantly share code, notes, and snippets.

@ldaley
Created May 6, 2021 03:39
Show Gist options
  • Save ldaley/6cc6031cf90882100545342cf94ed7a6 to your computer and use it in GitHub Desktop.
Save ldaley/6cc6031cf90882100545342cf94ed7a6 to your computer and use it in GitHub Desktop.
diff --git a/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/CustomSessionModule.java b/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/CustomSessionModule.java
index 779a08fa6c2..e9d287631b2 100644
--- a/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/CustomSessionModule.java
+++ b/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/CustomSessionModule.java
@@ -6,6 +6,7 @@ import com.google.inject.Provides;
import com.google.inject.util.Modules;
import com.gradle.ratpack.appmeta.mode.ApplicationEnv;
import com.gradle.ratpack.appmeta.mode.ApplicationMode;
+import com.gradle.ratpack.feature.Feature;
import com.gradle.ratpack.util.UnhandledSwitchValueException;
import com.gradle.ratpack.util.uuid.UniqueId;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -32,6 +33,12 @@ public final class CustomSessionModule extends AbstractModule {
@Override
protected void configure() {
+ Feature.of(NewSessionFormatFeature.class, binder(), s -> s
+ .optionalInAllEnvs()
+ .defaultEnabled(m -> false)
+ .allowRequestOverride(m -> true)
+ );
+
switch (storageType) {
case CLIENT:
install(
@@ -55,7 +62,9 @@ public final class CustomSessionModule extends AbstractModule {
@Override
protected void configure() {
- bind(JavaSessionSerializer.class).to(ObfuscationAwareKryoSessionSerializer.class);
+ bind(JavaSessionSerializer.class).to(TogglingSessionSerializer.class);
+ bind(ObfuscationAwareKryoSessionSerializer.class);
+ bind(KryoSessionSerializer.class);
}
}
diff --git a/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/KryoSessionSerializer.java b/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/KryoSessionSerializer.java
new file mode 100644
index 00000000000..493ea2d4c98
--- /dev/null
+++ b/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/KryoSessionSerializer.java
@@ -0,0 +1,57 @@
+package com.gradle.ratpack.session;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.KryoObjectInput;
+import com.esotericsoftware.kryo.io.KryoObjectOutput;
+import com.esotericsoftware.kryo.io.Output;
+import com.google.inject.Singleton;
+import com.gradle.obfuscation.ObfuscationControl;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import io.netty.util.concurrent.FastThreadLocal;
+import org.objenesis.strategy.StdInstantiatorStrategy;
+import ratpack.session.JavaSessionSerializer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.OutputStream;
+
+@Singleton
+final class KryoSessionSerializer implements JavaSessionSerializer {
+
+ private static final FastThreadLocal<Kryo> KRYO = new FastThreadLocal<Kryo>() {
+ @Override
+ protected Kryo initialValue() {
+ Kryo kryo = new Kryo();
+ kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
+ kryo.setClassLoader(Thread.currentThread().getContextClassLoader());
+ return kryo;
+ }
+ };
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public <T> void serialize(Class<T> type, T value, OutputStream out) throws IOException {
+ ObfuscationControl.requireClassName(type, () -> "class is serialized into session");
+ try (ObjectOutput objectOut = new KryoObjectOutput(KRYO.get(), new Output(out))) {
+ objectOut.writeObject(value);
+ }
+ }
+
+ @Override
+ @SuppressFBWarnings(value = "SECOBDES", justification = "object deserialization is intentional")
+ @SuppressWarnings("deprecation")
+ public <T> T deserialize(Class<T> type, InputStream in) throws Exception {
+ try (ObjectInput objectInput = new KryoObjectInput(KRYO.get(), new Input(in))) {
+ Object obj = objectInput.readObject();
+ if (type.isInstance(obj)) {
+ return type.cast(obj);
+ } else {
+ throw new IllegalStateException("Expected " + type + " got " + obj.getClass());
+ }
+ }
+ }
+
+}
diff --git a/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/NewSessionFormatFeature.java b/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/NewSessionFormatFeature.java
new file mode 100644
index 00000000000..cbb56d8b2f4
--- /dev/null
+++ b/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/NewSessionFormatFeature.java
@@ -0,0 +1,8 @@
+package com.gradle.ratpack.session;
+
+import com.gradle.obfuscation.KeepName;
+import com.gradle.ratpack.feature.Feature;
+
+@KeepName
+public interface NewSessionFormatFeature extends Feature {
+}
diff --git a/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/TogglingSessionSerializer.java b/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/TogglingSessionSerializer.java
new file mode 100644
index 00000000000..54866eb44cb
--- /dev/null
+++ b/ratpack-app-lib-common/src/main/java/com/gradle/ratpack/session/TogglingSessionSerializer.java
@@ -0,0 +1,46 @@
+package com.gradle.ratpack.session;
+
+import ratpack.session.JavaSessionSerializer;
+import ratpack.session.SessionTypeFilter;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+@Singleton
+final class TogglingSessionSerializer implements JavaSessionSerializer {
+
+ private final NewSessionFormatFeature feature;
+ private final KryoSessionSerializer oldSerializer;
+ private final ObfuscationAwareKryoSessionSerializer newSerializer;
+
+ @Inject
+ TogglingSessionSerializer(
+ NewSessionFormatFeature feature,
+ KryoSessionSerializer oldSerializer,
+ ObfuscationAwareKryoSessionSerializer newSerializer
+ ) {
+ this.feature = feature;
+ this.oldSerializer = oldSerializer;
+ this.newSerializer = newSerializer;
+ }
+
+ @Override
+ public <T> void serialize(Class<T> type, T value, OutputStream out, SessionTypeFilter typeFilter) throws Exception {
+ if (feature.isEnabled()) {
+ newSerializer.serialize(type, value, out, typeFilter);
+ } else {
+ oldSerializer.serialize(type, value, out, typeFilter);
+ }
+ }
+
+ @Override
+ public <T> T deserialize(Class<T> type, InputStream in, SessionTypeFilter typeFilter) throws Exception {
+ if (feature.isEnabled()) {
+ return newSerializer.deserialize(type, in, typeFilter);
+ } else {
+ return oldSerializer.deserialize(type, in, typeFilter);
+ }
+ }
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment