forked from ehcache/ehcache3
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🐛 ehcache#1814 StateRepository data format change
The StateRepository provided map for a clustered cache cannot store any Serializable type as otherwise the server will fail to deserialize classes not on its classpath. So keys and values are encoded to preserve usage flexibility while providing a best effort on equality contract.
- Loading branch information
Showing
6 changed files
with
282 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
clustered/client/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodec.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
* Copyright Terracotta, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.ehcache.clustered.client.internal.service; | ||
|
||
/** | ||
* ValueCodec | ||
*/ | ||
interface ValueCodec<T> { | ||
|
||
Object encode(T input); | ||
|
||
T decode(Object input); | ||
} |
105 changes: 105 additions & 0 deletions
105
...client/src/main/java/org/ehcache/clustered/client/internal/service/ValueCodecFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Copyright Terracotta, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.ehcache.clustered.client.internal.service; | ||
|
||
import org.ehcache.clustered.common.internal.store.ValueWrapper; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.io.ObjectInputStream; | ||
import java.io.ObjectOutputStream; | ||
import java.io.Serializable; | ||
|
||
/** | ||
* ValueCodecFactory | ||
*/ | ||
class ValueCodecFactory { | ||
static <T> ValueCodec<T> getCodecForClass(Class<T> clazz) { | ||
if (!Serializable.class.isAssignableFrom(clazz)) { | ||
throw new IllegalArgumentException("The provided type is invalid as it is not Serializable " + clazz); | ||
} | ||
if (Integer.class.equals(clazz) || Long.class.equals(clazz) | ||
|| Float.class.equals(clazz) || Double.class.equals(clazz) | ||
|| Byte.class.equals(clazz) || Character.class.equals(clazz) | ||
|| clazz.isPrimitive() || String.class.equals(clazz)) { | ||
return new IdentityCodec<T>(); | ||
} else { | ||
return new SerializationWrapperCodec<T>(); | ||
} | ||
} | ||
|
||
private static class IdentityCodec<T> implements ValueCodec<T> { | ||
@Override | ||
public Object encode(T input) { | ||
return input; | ||
} | ||
|
||
@Override | ||
@SuppressWarnings("unchcked") | ||
public T decode(Object input) { | ||
return (T) input; | ||
} | ||
} | ||
|
||
private static class SerializationWrapperCodec<T> implements ValueCodec<T> { | ||
@Override | ||
public Object encode(T input) { | ||
if (input == null) { | ||
return null; | ||
} | ||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||
try { | ||
ObjectOutputStream oos = new ObjectOutputStream(baos); | ||
try { | ||
oos.writeObject(input); | ||
} catch(IOException e) { | ||
throw new RuntimeException("Object cannot be serialized", e); | ||
} finally { | ||
oos.close(); | ||
} | ||
} catch(IOException e) { | ||
// ignore | ||
} | ||
return new ValueWrapper(input.hashCode(), baos.toByteArray()); | ||
} | ||
|
||
@Override | ||
public T decode(Object input) { | ||
if (input == null) { | ||
return null; | ||
} | ||
ValueWrapper data = (ValueWrapper) input; | ||
ByteArrayInputStream bais = new ByteArrayInputStream(data.getValue()); | ||
try { | ||
ObjectInputStream ois = new ObjectInputStream(bais); | ||
try { | ||
@SuppressWarnings("unchecked") | ||
T result = (T) ois.readObject(); | ||
return result; | ||
} catch (ClassNotFoundException e) { | ||
throw new RuntimeException("Could not load class", e); | ||
} finally { | ||
ois.close(); | ||
} | ||
} catch(IOException e) { | ||
// ignore | ||
} | ||
throw new AssertionError("Cannot reach here!"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
clustered/common/src/main/java/org/ehcache/clustered/common/internal/store/ValueWrapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* Copyright Terracotta, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.ehcache.clustered.common.internal.store; | ||
|
||
import java.io.Serializable; | ||
import java.util.Arrays; | ||
|
||
/** | ||
* ValueWrapper | ||
*/ | ||
public class ValueWrapper implements Serializable { | ||
|
||
private static final long serialVersionUID = -4794738044295644587L; | ||
|
||
private final int hashCode; | ||
private final byte[] value; | ||
|
||
public ValueWrapper(int hashCode, byte[] value) { | ||
this.hashCode = hashCode; | ||
this.value = value; | ||
} | ||
|
||
public byte[] getValue() { | ||
return value; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
|
||
ValueWrapper that = (ValueWrapper) o; | ||
|
||
if (hashCode != that.hashCode) return false; | ||
return Arrays.equals(value, that.value); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return hashCode; | ||
} | ||
} |