/** * Reads from a data input view a {@link TypeSerializer} that was previously * written using {@link #writeSerializer(DataOutputView, TypeSerializer)}. * * <p>If deserialization fails for any reason (corrupted serializer bytes, serializer class * no longer in classpath, serializer class no longer valid, etc.), an {@link IOException} is thrown. * * @param in the data input view. * @param userCodeClassLoader the user code class loader to use. * * @param <T> Data type of the serializer. * * @return the deserialized serializer. */ public static <T> TypeSerializer<T> tryReadSerializer(DataInputView in, ClassLoader userCodeClassLoader) throws IOException { return tryReadSerializer(in, userCodeClassLoader, false); }
@Override public final void readSnapshot(int readVersion, DataInputView in, ClassLoader userCodeClassLoader) throws IOException { if (readVersion != ADAPTER_VERSION) { throw new IOException("Wrong/unexpected version for the TypeSerializerConfigSnapshot: " + readVersion); } serializer = TypeSerializerSerializationUtil.tryReadSerializer(in, userCodeClassLoader, true); // now delegate to the snapshots own reading code setUserCodeClassLoader(userCodeClassLoader); read(in); }
@SuppressWarnings("deprecation") private static TypeSerializer<?> javaDeserialize(String base64) throws IOException { byte[] bytes = Base64.getMimeDecoder().decode(base64); DataInputDeserializer in = new DataInputDeserializer(bytes); return TypeSerializerSerializationUtil.tryReadSerializer(in, Thread.currentThread().getContextClassLoader()); }
@Test public void testDeserializingKryoSerializerWithoutAvro() throws Exception { final String resource = "serialized-kryo-serializer-1.3"; TypeSerializer<?> serializer; try (InputStream in = getClass().getClassLoader().getResourceAsStream(resource)) { DataInputViewStreamWrapper inView = new DataInputViewStreamWrapper(in); serializer = TypeSerializerSerializationUtil.tryReadSerializer(inView, getClass().getClassLoader()); } assertNotNull(serializer); assertTrue(serializer instanceof KryoSerializer); }
/** * Verifies that serializers of anonymous classes can be deserialized, even if serialVersionUID changes. */ @Test public void testAnonymousSerializerClassWithChangedSerialVersionUID() throws Exception { TypeSerializer anonymousClassSerializer = new AbstractIntSerializer() {}; // assert that our assumption holds Assert.assertTrue(anonymousClassSerializer.getClass().isAnonymousClass()); byte[] anonymousSerializerBytes; try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { TypeSerializerSerializationUtil.writeSerializer(new DataOutputViewStreamWrapper(out), anonymousClassSerializer); anonymousSerializerBytes = out.toByteArray(); } long newSerialVersionUID = 1234567L; // assert that we're actually modifying to a different serialVersionUID Assert.assertNotEquals(ObjectStreamClass.lookup(anonymousClassSerializer.getClass()).getSerialVersionUID(), newSerialVersionUID); modifySerialVersionUID(anonymousSerializerBytes, anonymousClassSerializer.getClass().getName(), newSerialVersionUID); try (ByteArrayInputStream in = new ByteArrayInputStream(anonymousSerializerBytes)) { anonymousClassSerializer = TypeSerializerSerializationUtil.tryReadSerializer(new DataInputViewStreamWrapper(in), Thread.currentThread().getContextClassLoader()); } // serializer should have been deserialized despite serialVersionUID mismatch Assert.assertNotNull(anonymousClassSerializer); Assert.assertTrue(anonymousClassSerializer.getClass().isAnonymousClass()); }
serializer = tryReadSerializer(bufferWrapper, userCodeClassLoader, true);
/** * Verifies deserialization failure cases when reading a serializer from bytes, in the * case of a {@link InvalidClassException}. */ @Test public void testSerializerSerializationWithInvalidClass() throws Exception { TypeSerializer<?> serializer = IntSerializer.INSTANCE; byte[] serialized; try (ByteArrayOutputStreamWithPos out = new ByteArrayOutputStreamWithPos()) { TypeSerializerSerializationUtil.writeSerializer(new DataOutputViewStreamWrapper(out), serializer); serialized = out.toByteArray(); } TypeSerializer<?> deserializedSerializer; try (ByteArrayInputStreamWithPos in = new ByteArrayInputStreamWithPos(serialized)) { deserializedSerializer = TypeSerializerSerializationUtil.tryReadSerializer( new DataInputViewStreamWrapper(in), new ArtificialCNFExceptionThrowingClassLoader( Thread.currentThread().getContextClassLoader(), Collections.singleton(IntSerializer.class.getName())), true); } Assert.assertTrue(deserializedSerializer instanceof UnloadableDummyTypeSerializer); }
fieldSerializer = TypeSerializerSerializationUtil.tryReadSerializer(inViewWrapper, getUserCodeClassLoader(), true); registeredSubclassSerializer = TypeSerializerSerializationUtil.tryReadSerializer(inViewWrapper, getUserCodeClassLoader(), true); cachedSubclassSerializer = TypeSerializerSerializationUtil.tryReadSerializer(inViewWrapper, getUserCodeClassLoader(), true);
/** * Verifies that reading and writing serializers work correctly. */ @Test public void testSerializerSerialization() throws Exception { TypeSerializer<?> serializer = IntSerializer.INSTANCE; byte[] serialized; try (ByteArrayOutputStreamWithPos out = new ByteArrayOutputStreamWithPos()) { TypeSerializerSerializationUtil.writeSerializer(new DataOutputViewStreamWrapper(out), serializer); serialized = out.toByteArray(); } TypeSerializer<?> deserializedSerializer; try (ByteArrayInputStreamWithPos in = new ByteArrayInputStreamWithPos(serialized)) { deserializedSerializer = TypeSerializerSerializationUtil.tryReadSerializer( new DataInputViewStreamWrapper(in), Thread.currentThread().getContextClassLoader()); } Assert.assertEquals(serializer, deserializedSerializer); }
/** * Verifies deserialization failure cases when reading a serializer from bytes, in the * case of a {@link ClassNotFoundException}. */ @Test public void testSerializerSerializationWithClassNotFound() throws Exception { TypeSerializer<?> serializer = IntSerializer.INSTANCE; byte[] serialized; try (ByteArrayOutputStreamWithPos out = new ByteArrayOutputStreamWithPos()) { TypeSerializerSerializationUtil.writeSerializer(new DataOutputViewStreamWrapper(out), serializer); serialized = out.toByteArray(); } TypeSerializer<?> deserializedSerializer; try (ByteArrayInputStreamWithPos in = new ByteArrayInputStreamWithPos(serialized)) { deserializedSerializer = TypeSerializerSerializationUtil.tryReadSerializer( new DataInputViewStreamWrapper(in), new ArtificialCNFExceptionThrowingClassLoader( Thread.currentThread().getContextClassLoader(), Collections.singleton(IntSerializer.class.getName())), true); } Assert.assertTrue(deserializedSerializer instanceof UnloadableDummyTypeSerializer); Assert.assertArrayEquals( InstantiationUtil.serializeObject(serializer), ((UnloadableDummyTypeSerializer<?>) deserializedSerializer).getActualBytes()); }
/** * Reads from a data input view a {@link TypeSerializer} that was previously * written using {@link #writeSerializer(DataOutputView, TypeSerializer)}. * * <p>If deserialization fails for any reason (corrupted serializer bytes, serializer class * no longer in classpath, serializer class no longer valid, etc.), an {@link IOException} is thrown. * * @param in the data input view. * @param userCodeClassLoader the user code class loader to use. * * @param <T> Data type of the serializer. * * @return the deserialized serializer. */ public static <T> TypeSerializer<T> tryReadSerializer(DataInputView in, ClassLoader userCodeClassLoader) throws IOException { return tryReadSerializer(in, userCodeClassLoader, false); }
/** * Reads from a data input view a {@link TypeSerializer} that was previously * written using {@link #writeSerializer(DataOutputView, TypeSerializer)}. * * <p>If deserialization fails for any reason (corrupted serializer bytes, serializer class * no longer in classpath, serializer class no longer valid, etc.), an {@link IOException} is thrown. * * @param in the data input view. * @param userCodeClassLoader the user code class loader to use. * * @param <T> Data type of the serializer. * * @return the deserialized serializer. */ public static <T> TypeSerializer<T> tryReadSerializer(DataInputView in, ClassLoader userCodeClassLoader) throws IOException { return tryReadSerializer(in, userCodeClassLoader, false); }
@Override public final void readSnapshot(int readVersion, DataInputView in, ClassLoader userCodeClassLoader) throws IOException { if (readVersion != ADAPTER_VERSION) { throw new IOException("Wrong/unexpected version for the TypeSerializerConfigSnapshot: " + readVersion); } serializer = TypeSerializerSerializationUtil.tryReadSerializer(in, userCodeClassLoader, true); // now delegate to the snapshots own reading code setUserCodeClassLoader(userCodeClassLoader); read(in); }
@Nonnull @Override public StateMetaInfoSnapshot readStateMetaInfoSnapshot( @Nonnull DataInputView in, @Nonnull ClassLoader userCodeClassLoader) throws IOException { final StateDescriptor.Type stateDescType = StateDescriptor.Type.values()[in.readInt()]; final String stateName = in.readUTF(); Map<String, String> optionsMap = Collections.singletonMap( StateMetaInfoSnapshot.CommonOptionsKeys.KEYED_STATE_TYPE.toString(), stateDescType.toString()); Map<String, TypeSerializerSnapshot<?>> serializerConfigSnapshotMap = new HashMap<>(2); serializerConfigSnapshotMap.put( StateMetaInfoSnapshot.CommonSerializerKeys.NAMESPACE_SERIALIZER.toString(), new BackwardsCompatibleSerializerSnapshot<>( TypeSerializerSerializationUtil.tryReadSerializer(in, userCodeClassLoader, true))); serializerConfigSnapshotMap.put( StateMetaInfoSnapshot.CommonSerializerKeys.VALUE_SERIALIZER.toString(), new BackwardsCompatibleSerializerSnapshot<>( TypeSerializerSerializationUtil.tryReadSerializer(in, userCodeClassLoader, true))); return new StateMetaInfoSnapshot( stateName, StateMetaInfoSnapshot.BackendStateType.KEY_VALUE, optionsMap, serializerConfigSnapshotMap); } }
@Nonnull @Override public StateMetaInfoSnapshot readStateMetaInfoSnapshot( @Nonnull DataInputView in, @Nonnull ClassLoader userCodeClassLoader) throws IOException { final StateDescriptor.Type stateDescType = StateDescriptor.Type.values()[in.readInt()]; final String stateName = in.readUTF(); Map<String, String> optionsMap = Collections.singletonMap( StateMetaInfoSnapshot.CommonOptionsKeys.KEYED_STATE_TYPE.toString(), stateDescType.toString()); Map<String, TypeSerializerSnapshot<?>> serializerConfigSnapshotMap = new HashMap<>(2); serializerConfigSnapshotMap.put( StateMetaInfoSnapshot.CommonSerializerKeys.NAMESPACE_SERIALIZER.toString(), new BackwardsCompatibleSerializerSnapshot<>( TypeSerializerSerializationUtil.tryReadSerializer(in, userCodeClassLoader, true))); serializerConfigSnapshotMap.put( StateMetaInfoSnapshot.CommonSerializerKeys.VALUE_SERIALIZER.toString(), new BackwardsCompatibleSerializerSnapshot<>( TypeSerializerSerializationUtil.tryReadSerializer(in, userCodeClassLoader, true))); return new StateMetaInfoSnapshot( stateName, StateMetaInfoSnapshot.BackendStateType.KEY_VALUE, optionsMap, serializerConfigSnapshotMap); } }
@SuppressWarnings("unchecked") @Override public void read(DataInputView in) throws IOException { super.read(in); // only starting from version 3, we have the key serializer and its config snapshot written if (getReadVersion() >= 3) { Tuple2<TypeSerializer<?>, TypeSerializerConfigSnapshot> keySerializerAndConfig = TypeSerializerSerializationUtil.readSerializersAndConfigsWithResilience(in, userCodeClassLoader).get(0); this.keySerializer = (TypeSerializer<K>) keySerializerAndConfig.f0; this.keySerializerConfigSnapshot = keySerializerAndConfig.f1; } else { this.keySerializer = TypeSerializerSerializationUtil.tryReadSerializer(in, userCodeClassLoader); this.keySerializerConfigSnapshot = null; } int numKvStates = in.readShort(); stateMetaInfoSnapshots = new ArrayList<>(numKvStates); for (int i = 0; i < numKvStates; i++) { stateMetaInfoSnapshots.add( KeyedBackendStateMetaInfoSnapshotReaderWriters .getReaderForVersion(getReadVersion(), userCodeClassLoader) .readStateMetaInfo(in)); } } }
@Override public RegisteredKeyedBackendStateMetaInfo.Snapshot<N, S> readStateMetaInfo(DataInputView in) throws IOException { RegisteredKeyedBackendStateMetaInfo.Snapshot<N, S> metaInfo = new RegisteredKeyedBackendStateMetaInfo.Snapshot<>(); metaInfo.setStateType(StateDescriptor.Type.values()[in.readInt()]); metaInfo.setName(in.readUTF()); metaInfo.setNamespaceSerializer(TypeSerializerSerializationUtil.<N>tryReadSerializer(in, userCodeClassLoader, true)); metaInfo.setStateSerializer(TypeSerializerSerializationUtil.<S>tryReadSerializer(in, userCodeClassLoader, true)); // older versions do not contain the configuration snapshot metaInfo.setNamespaceSerializerConfigSnapshot(null); metaInfo.setStateSerializerConfigSnapshot(null); return metaInfo; } }
@Override public RegisteredKeyedBackendStateMetaInfo.Snapshot<N, S> readStateMetaInfo(DataInputView in) throws IOException { RegisteredKeyedBackendStateMetaInfo.Snapshot<N, S> metaInfo = new RegisteredKeyedBackendStateMetaInfo.Snapshot<>(); metaInfo.setStateType(StateDescriptor.Type.values()[in.readInt()]); metaInfo.setName(in.readUTF()); metaInfo.setNamespaceSerializer(TypeSerializerSerializationUtil.<N>tryReadSerializer(in, userCodeClassLoader)); metaInfo.setStateSerializer(TypeSerializerSerializationUtil.<S>tryReadSerializer(in, userCodeClassLoader)); // older versions do not contain the configuration snapshot metaInfo.setNamespaceSerializerConfigSnapshot(null); metaInfo.setStateSerializerConfigSnapshot(null); return metaInfo; } }
} else { this.keySerializerConfigSnapshot = new BackwardsCompatibleSerializerSnapshot<>( TypeSerializerSerializationUtil.tryReadSerializer(in, userCodeClassLoader, true));
this.keySerializerConfigSnapshot = keySerializerAndConfig.f1; } else { this.keySerializer = TypeSerializerSerializationUtil.tryReadSerializer(in, userCodeClassLoader, true); this.keySerializerConfigSnapshot = null;