forked from apache/doris
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
583fc31
commit fafe881
Showing
6 changed files
with
192 additions
and
3 deletions.
There are no files selected for viewing
71 changes: 71 additions & 0 deletions
71
fe/fe-core/src/main/java/org/apache/doris/common/util/SerializationUtils.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,71 @@ | ||
// Licensed to the Apache Software Foundation (ASF) under one | ||
// or more contributor license agreements. See the NOTICE file | ||
// distributed with this work for additional information | ||
// regarding copyright ownership. The ASF licenses this file | ||
// to you 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.apache.doris.common.util; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.io.ObjectInputStream; | ||
import java.io.ObjectOutputStream; | ||
import java.io.Serializable; | ||
|
||
/** | ||
* A utility class for serializing and deep cloning Serializable objects. | ||
* <p> | ||
* This class provides a method to clone an object by serializing it to a byte array | ||
* and then deserializing it back to an object. This approach ensures that a deep copy | ||
* is created, meaning that all objects referenced by the original object are also cloned. | ||
* <p> | ||
* Note: The object to be cloned must implement the {@link Serializable} interface. | ||
*/ | ||
public class SerializationUtils { | ||
|
||
/** | ||
* Clones a Serializable object by serializing and deserializing it. | ||
* | ||
* @param object the object to be cloned. Must be Serializable. | ||
* @param <T> the type of the object to clone. Must extend Serializable. | ||
* @return a deep copy of the provided object, or null if the input object is null. | ||
* @throws RuntimeException if cloning fails due to I/O or class not found exceptions. | ||
*/ | ||
public static <T> T clone(final T object) { | ||
// Check if the object is null; if true, return null | ||
if (object == null) { | ||
return null; // Return null for null input | ||
} | ||
|
||
try { | ||
// Serialize the object to a byte array | ||
try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Output stream to hold the serialized data | ||
ObjectOutputStream oos = new ObjectOutputStream(baos)) { // ObjectOutputStream for serialization | ||
oos.writeObject(object); // Write the object to the output stream | ||
oos.flush(); // Ensure all data is written | ||
|
||
// Deserialize the byte array back to an object | ||
// Input stream from byte array | ||
try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); | ||
ObjectInputStream ois = new ObjectInputStream(bais)) { // ObjectInputStream for deserialization | ||
return (T) ois.readObject(); // Read and return the cloned object | ||
} | ||
} | ||
} catch (IOException | ClassNotFoundException e) { | ||
// Wrap any exceptions thrown during serialization/deserialization | ||
throw new RuntimeException("Cloning failed", e); | ||
} | ||
} | ||
} |
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
110 changes: 110 additions & 0 deletions
110
fe/fe-core/src/test/java/org/apache/doris/common/util/SerializationUtilsTest.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,110 @@ | ||
// Licensed to the Apache Software Foundation (ASF) under one | ||
// or more contributor license agreements. See the NOTICE file | ||
// distributed with this work for additional information | ||
// regarding copyright ownership. The ASF licenses this file | ||
// to you 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.apache.doris.common.util; | ||
|
||
import org.junit.jupiter.api.Assertions; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.io.Serializable; | ||
import java.util.HashMap; | ||
import java.util.Objects; | ||
|
||
public class SerializationUtilsTest { | ||
|
||
|
||
private final HashMap<String, Object> sampleMap = new HashMap<>(); | ||
private final String sampleString = "sampleString"; | ||
private final Integer sampleInteger = 456; | ||
|
||
public SerializationUtilsTest() { | ||
sampleMap.put("KEY_ONE", sampleString); | ||
sampleMap.put("KEY_TWO", sampleInteger); | ||
} | ||
|
||
@Test | ||
public void testClone() { | ||
final Object clonedObject = SerializationUtils.clone(sampleMap); | ||
Assertions.assertNotNull(clonedObject); | ||
Assertions.assertTrue(clonedObject instanceof HashMap<?, ?>); | ||
Assertions.assertNotSame(clonedObject, sampleMap); | ||
|
||
final HashMap<?, ?> clonedMap = (HashMap<?, ?>) clonedObject; | ||
Assertions.assertEquals(sampleString, clonedMap.get("KEY_ONE")); | ||
Assertions.assertNotSame(sampleString, clonedMap.get("KEY_ONE")); | ||
Assertions.assertEquals(sampleInteger, clonedMap.get("KEY_TWO")); | ||
Assertions.assertNotSame(sampleInteger, clonedMap.get("KEY_TWO")); | ||
Assertions.assertEquals(sampleMap, clonedMap); | ||
} | ||
|
||
@Test | ||
public void testCloneNull() { | ||
final Object clonedObject = SerializationUtils.clone(null); | ||
Assertions.assertNull(clonedObject); | ||
} | ||
|
||
@Test | ||
public void testCloneWithWriteReplace() { | ||
Child childObject = new Child(true); | ||
Parent clonedParent = SerializationUtils.clone(childObject); | ||
|
||
Assertions.assertNotSame(childObject, clonedParent); | ||
Assertions.assertEquals(new Parent(true), clonedParent); | ||
} | ||
|
||
static class Parent implements Serializable { | ||
private static final long serialVersionUID = 1L; | ||
protected boolean status; | ||
|
||
Parent(boolean status) { | ||
this.status = status; | ||
} | ||
|
||
protected Parent(Parent parent) { | ||
this.status = parent.status; | ||
} | ||
|
||
protected Object writeReplace() { | ||
return new Parent(this); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(status); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) { | ||
return true; | ||
} | ||
if (obj == null || getClass() != obj.getClass()) { | ||
return false; | ||
} | ||
Parent other = (Parent) obj; | ||
return status == other.status; | ||
} | ||
} | ||
|
||
static class Child extends Parent { | ||
private static final long serialVersionUID = 2L; | ||
|
||
Child(boolean status) { | ||
super(status); | ||
} | ||
} | ||
} |
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