Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 59 additions & 15 deletions server/src/main/java/com/cloud/api/ApiSerializerHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
// under the License.
package com.cloud.api;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

import com.cloud.utils.exception.CloudRuntimeException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
Expand All @@ -31,38 +34,51 @@
public class ApiSerializerHelper {
protected static Logger LOGGER = LogManager.getLogger(ApiSerializerHelper.class);
private static String token = "/";
private static String[] apiPackages = {"com.cloud.agent.api", "org.apache.cloudstack.api"};

public static String toSerializedString(Object result) {
if (result != null) {
Class<?> clz = result.getClass();
/**
* serialise an object's class to a {@link String}
* @param inputObject
* @return
*/
public static String toSerializedString(Object inputObject) {
if (inputObject != null) {
Class<?> clz = inputObject.getClass();
Gson gson = ApiGsonHelper.getBuilder().create();

if (result instanceof ResponseObject) {
return clz.getName() + token + ((ResponseObject)result).getObjectName() + token + gson.toJson(result);
if (inputObject instanceof ResponseObject) {
return clz.getName() + token + ((ResponseObject)inputObject).getObjectName() + token + gson.toJson(inputObject);
} else {
return clz.getName() + token + gson.toJson(result);
return clz.getName() + token + gson.toJson(inputObject);
}
}
return null;
}

public static Object fromSerializedString(String result) {
/**
* deserialise an {@link Object} from a {@link String}
*
* @param classString the string representation of the {@link Class} instance to create
* @return an {@link Object} of the requested {@link Class} type
*/
public static Object fromSerializedString(String classString) {
try {
if (result != null && !result.isEmpty()) {
String[] serializedParts = result.split(token);
if (classString != null && !classString.isEmpty()) {
String[] serializedParts = classString.split(token);

if (serializedParts.length < 2) {
return null;
}
String clzName = serializedParts[0];
validateClassPath(clzName, apiPackages);
String nameField = null;
String content = null;
if (serializedParts.length == 2) {
content = serializedParts[1];
} else {
nameField = serializedParts[1];
int index = result.indexOf(token + nameField + token);
content = result.substring(index + nameField.length() + 2);
int index = classString.indexOf(token + nameField + token);
content = classString.substring(index + nameField.length() + 2);
}

Class<?> clz;
Expand All @@ -81,15 +97,43 @@ public static Object fromSerializedString(String result) {
}
return null;
} catch (RuntimeException e) {
LOGGER.error("Caught runtime exception when doing GSON deserialization on: " + result);
LOGGER.error("Caught runtime exception when doing GSON deserialization on: " + classString);
throw e;
}
}

public static Map<String, Object> fromSerializedStringToMap(String result) {
/**
* validates that a class is allowed to be deserialised.
*
* TODO move to a more globally accessible util class
* TODO make generic for allow lists
* TODO extend to return the desired class
*
* @param clzName
* @param basePaths
*/
private static void validateClassPath(String clzName, String[] basePaths) {
if (clzName != null) {
for (String basePath : basePaths) {
if (clzName.startsWith(basePath)) {
return;
}
}
}
String packages = Arrays.toString(basePaths);
throw new CloudRuntimeException(String.format("illegal to load \"%s\" forName, only classes in packages \"%s\" are allowed", clzName, packages));
}

/**
* deserialise a map
*
* @param mapRepresentation the {@link String} representation of the {@link Map<>} type
* @return the {@link Map<>} object
*/
public static Map<String, Object> fromSerializedStringToMap(String mapRepresentation) {
Map<String,Object> objParams = null;
try {
Object obj = fromSerializedString(result);
Object obj = fromSerializedString(mapRepresentation);
if (obj != null) {
Gson gson = ApiGsonHelper.getBuilder().create();
String objJson = gson.toJson(obj);
Expand All @@ -102,7 +146,7 @@ public static Map<String, Object> fromSerializedStringToMap(String result) {
}
}
} catch (RuntimeException | JsonProcessingException e) {
LOGGER.error("Caught runtime exception when doing GSON deserialization to map on: " + result, e);
LOGGER.error("Caught runtime exception when doing GSON deserialization to map on: " + mapRepresentation, e);
}

return objParams;
Expand Down
Loading