mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-8485: listAPIs are taking too long to return results
- Removed regex. based search/replace of sensitive data on API response introduced as part of commit b0c6d4734724358df97b6fa4d8c5beb0f447745e - Added new response serializer to skip sensitive data from getting logged based on annotation present in resposne object fields - Added new parameter 'isSensitive' to @Param for marking a field as sensitive in response objects
This commit is contained in:
parent
acce645119
commit
e13df96348
@ -37,4 +37,6 @@ public @interface Param {
|
||||
String since() default "";
|
||||
|
||||
RoleType[] authorized() default {};
|
||||
|
||||
boolean isSensitive() default false;
|
||||
}
|
||||
|
||||
@ -17,13 +17,12 @@
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
|
||||
public class CreateSSHKeyPairResponse extends SSHKeyPairResponse {
|
||||
|
||||
@SerializedName("privatekey")
|
||||
@Param(description = "Private key")
|
||||
@Param(description = "Private key", isSensitive = true)
|
||||
private String privateKey;
|
||||
|
||||
public CreateSSHKeyPairResponse() {
|
||||
|
||||
@ -25,7 +25,7 @@ import com.cloud.serializer.Param;
|
||||
public class GetVMPasswordResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("encryptedpassword")
|
||||
@Param(description = "The base64 encoded encrypted password of the VM")
|
||||
@Param(description = "The base64 encoded encrypted password of the VM", isSensitive = true)
|
||||
private String encryptedPassword;
|
||||
|
||||
public GetVMPasswordResponse() {
|
||||
|
||||
@ -63,7 +63,7 @@ public class LoginCmdResponse extends AuthenticationCmdResponse {
|
||||
private String registered;
|
||||
|
||||
@SerializedName(value = ApiConstants.SESSIONKEY)
|
||||
@Param(description = "Session key that can be passed in subsequent Query command calls")
|
||||
@Param(description = "Session key that can be passed in subsequent Query command calls", isSensitive = true)
|
||||
private String sessionKey;
|
||||
|
||||
public String getUsername() {
|
||||
|
||||
@ -24,11 +24,11 @@ import com.cloud.serializer.Param;
|
||||
|
||||
public class RegisterResponse extends BaseResponse {
|
||||
@SerializedName("apikey")
|
||||
@Param(description = "the api key of the registered user")
|
||||
@Param(description = "the api key of the registered user", isSensitive = true)
|
||||
private String apiKey;
|
||||
|
||||
@SerializedName("secretkey")
|
||||
@Param(description = "the secret key of the registered user")
|
||||
@Param(description = "the secret key of the registered user", isSensitive = true)
|
||||
private String secretKey;
|
||||
|
||||
public String getApiKey() {
|
||||
|
||||
@ -42,7 +42,7 @@ public class RemoteAccessVpnResponse extends BaseResponse implements ControlledE
|
||||
private String ipRange;
|
||||
|
||||
@SerializedName("presharedkey")
|
||||
@Param(description = "the ipsec preshared key")
|
||||
@Param(description = "the ipsec preshared key", isSensitive = true)
|
||||
private String presharedKey;
|
||||
|
||||
@SerializedName(ApiConstants.ACCOUNT)
|
||||
|
||||
@ -51,7 +51,7 @@ public class Site2SiteCustomerGatewayResponse extends BaseResponse implements Co
|
||||
private String guestCidrList;
|
||||
|
||||
@SerializedName(ApiConstants.IPSEC_PSK)
|
||||
@Param(description = "IPsec preshared-key of customer gateway")
|
||||
@Param(description = "IPsec preshared-key of customer gateway", isSensitive = true)
|
||||
private String ipsecPsk;
|
||||
|
||||
@SerializedName(ApiConstants.IKE_POLICY)
|
||||
|
||||
@ -58,7 +58,7 @@ public class Site2SiteVpnConnectionResponse extends BaseResponse implements Cont
|
||||
private String guestCidrList;
|
||||
|
||||
@SerializedName(ApiConstants.IPSEC_PSK)
|
||||
@Param(description = "IPsec Preshared-Key of the customer gateway")
|
||||
@Param(description = "IPsec Preshared-Key of the customer gateway", isSensitive = true)
|
||||
//from CustomerGateway
|
||||
private String ipsecPsk;
|
||||
|
||||
|
||||
@ -78,11 +78,11 @@ public class UserResponse extends BaseResponse {
|
||||
private String timezone;
|
||||
|
||||
@SerializedName("apikey")
|
||||
@Param(description = "the api key of the user")
|
||||
@Param(description = "the api key of the user", isSensitive = true)
|
||||
private String apiKey;
|
||||
|
||||
@SerializedName("secretkey")
|
||||
@Param(description = "the secret key of the user")
|
||||
@Param(description = "the secret key of the user", isSensitive = true)
|
||||
private String secretKey;
|
||||
|
||||
@SerializedName("accountid")
|
||||
|
||||
@ -221,7 +221,7 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
|
||||
private Set<SecurityGroupResponse> securityGroupList;
|
||||
|
||||
@SerializedName(ApiConstants.PASSWORD)
|
||||
@Param(description = "the password (if exists) of the virtual machine")
|
||||
@Param(description = "the password (if exists) of the virtual machine", isSensitive = true)
|
||||
private String password;
|
||||
|
||||
@SerializedName("nic")
|
||||
|
||||
@ -54,7 +54,7 @@ public class BigSwitchBcfDeviceResponse extends BaseResponse {
|
||||
@SerializedName(ApiConstants.USERNAME) @Param(description="the controller username")
|
||||
private String username;
|
||||
|
||||
@SerializedName(ApiConstants.PASSWORD) @Param(description="the controller password")
|
||||
@SerializedName(ApiConstants.PASSWORD) @Param(description="the controller password", isSensitive = true)
|
||||
private String password;
|
||||
|
||||
@SerializedName(BcfConstants.BIGSWITCH_BCF_DEVICE_NAT)
|
||||
|
||||
@ -53,7 +53,7 @@ public class LDAPConfigResponse extends BaseResponse {
|
||||
private String bindDN;
|
||||
|
||||
@SerializedName(ApiConstants.BIND_PASSWORD)
|
||||
@Param(description = "DN password")
|
||||
@Param(description = "DN password", isSensitive = true)
|
||||
private String bindPassword;
|
||||
|
||||
public String getHostname() {
|
||||
|
||||
@ -27,30 +27,40 @@ import com.google.gson.FieldAttributes;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
/**
|
||||
* The ApiResonseGsonHelper is different from ApiGsonHelper - it registeres one more adapter for String type required for api response encoding
|
||||
* The ApiResonseGsonHelper is different from ApiGsonHelper - it registers one more adapter for String type required for api response encoding
|
||||
*/
|
||||
public class ApiResponseGsonHelper {
|
||||
private static final GsonBuilder s_gBuilder;
|
||||
private static final GsonBuilder s_gLogBuilder;
|
||||
|
||||
static {
|
||||
s_gBuilder = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
|
||||
s_gBuilder.setVersion(1.3);
|
||||
s_gBuilder.registerTypeAdapter(ResponseObject.class, new ResponseObjectTypeAdapter());
|
||||
s_gBuilder.registerTypeAdapter(String.class, new EncodedStringTypeAdapter());
|
||||
s_gBuilder.setExclusionStrategies(new ExclStrat());
|
||||
s_gBuilder.setExclusionStrategies(new ApiResponseExclusionStrategy());
|
||||
|
||||
s_gLogBuilder = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
|
||||
s_gLogBuilder.setVersion(1.3);
|
||||
s_gLogBuilder.registerTypeAdapter(ResponseObject.class, new ResponseObjectTypeAdapter());
|
||||
s_gLogBuilder.registerTypeAdapter(String.class, new EncodedStringTypeAdapter());
|
||||
s_gLogBuilder.setExclusionStrategies(new LogExclusionStrategy());
|
||||
}
|
||||
|
||||
public static GsonBuilder getBuilder() {
|
||||
return s_gBuilder;
|
||||
}
|
||||
|
||||
private static class ExclStrat implements ExclusionStrategy {
|
||||
public static GsonBuilder getLogBuilder() {
|
||||
return s_gLogBuilder;
|
||||
}
|
||||
|
||||
private static class ApiResponseExclusionStrategy implements ExclusionStrategy {
|
||||
public boolean shouldSkipClass(Class<?> arg0) {
|
||||
return false;
|
||||
}
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
Param param = f.getAnnotation(Param.class);
|
||||
if (param != null) {
|
||||
RoleType[] allowedRoles = param.authorized();
|
||||
@ -71,4 +81,19 @@ public class ApiResponseGsonHelper {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class LogExclusionStrategy extends ApiResponseExclusionStrategy implements ExclusionStrategy {
|
||||
public boolean shouldSkipClass(Class<?> arg0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
Param param = f.getAnnotation(Param.class);
|
||||
boolean skip = (param != null && param.isSensitive());
|
||||
if (!skip) {
|
||||
skip = super.shouldSkipField(f);
|
||||
}
|
||||
return skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -525,14 +525,9 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
|
||||
cmdObj.setHttpMethod(paramMap.get(ApiConstants.HTTPMETHOD).toString());
|
||||
|
||||
// This is where the command is either serialized, or directly dispatched
|
||||
response = queueCommand(cmdObj, paramMap);
|
||||
if (annotation.responseHasSensitiveInfo())
|
||||
{
|
||||
buildAuditTrail(auditTrailSb, command[0],
|
||||
StringUtils.cleanString(response));
|
||||
}
|
||||
else
|
||||
buildAuditTrail(auditTrailSb, command[0], response);
|
||||
StringBuilder log = new StringBuilder();
|
||||
response = queueCommand(cmdObj, paramMap, log);
|
||||
buildAuditTrail(auditTrailSb, command[0], log.toString());
|
||||
} else {
|
||||
final String errorString = "Unknown API command: " + command[0];
|
||||
s_logger.warn(errorString);
|
||||
@ -617,7 +612,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
|
||||
return ApiResponseSerializer.toSerializedString(response, cmd.getResponseType());
|
||||
}
|
||||
|
||||
private String queueCommand(final BaseCmd cmdObj, final Map<String, String> params) throws Exception {
|
||||
private String queueCommand(final BaseCmd cmdObj, final Map<String, String> params, StringBuilder log) throws Exception {
|
||||
final CallContext ctx = CallContext.current();
|
||||
final Long callerUserId = ctx.getCallingUserId();
|
||||
final Account caller = ctx.getCallingAccount();
|
||||
@ -717,7 +712,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
|
||||
}
|
||||
|
||||
SerializationContext.current().setUuidTranslation(true);
|
||||
return ApiResponseSerializer.toSerializedString((ResponseObject)cmdObj.getResponseObject(), cmdObj.getResponseType());
|
||||
return ApiResponseSerializer.toSerializedStringWithSecureLogs((ResponseObject)cmdObj.getResponseObject(), cmdObj.getResponseType(), log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -147,8 +147,9 @@ public class ApiServlet extends HttpServlet {
|
||||
|
||||
// logging the request start and end in management log for easy debugging
|
||||
String reqStr = "";
|
||||
String cleanQueryString = StringUtils.cleanString(req.getQueryString());
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
reqStr = auditTrailSb.toString() + " " + StringUtils.cleanString(req.getQueryString());
|
||||
reqStr = auditTrailSb.toString() + " " + cleanQueryString;
|
||||
s_logger.debug("===START=== " + reqStr);
|
||||
}
|
||||
|
||||
@ -233,7 +234,7 @@ public class ApiServlet extends HttpServlet {
|
||||
}
|
||||
}
|
||||
|
||||
auditTrailSb.append(StringUtils.cleanString(req.getQueryString()));
|
||||
auditTrailSb.append(cleanQueryString);
|
||||
final boolean isNew = ((session == null) ? true : session.isNew());
|
||||
|
||||
// Initialize an empty context and we will update it after we have verified the request below,
|
||||
|
||||
@ -27,6 +27,7 @@ import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.exception.ExceptionProxyObject;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
@ -56,9 +57,18 @@ public class ApiResponseSerializer {
|
||||
public static String toSerializedString(ResponseObject result, String responseType) {
|
||||
s_logger.trace("===Serializing Response===");
|
||||
if (HttpUtils.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
|
||||
return toJSONSerializedString(result);
|
||||
return toJSONSerializedString(result, new StringBuilder());
|
||||
} else {
|
||||
return toXMLSerializedString(result);
|
||||
return toXMLSerializedString(result, new StringBuilder());
|
||||
}
|
||||
}
|
||||
|
||||
public static String toSerializedStringWithSecureLogs(ResponseObject result, String responseType, StringBuilder log) {
|
||||
s_logger.trace("===Serializing Response===");
|
||||
if (HttpUtils.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
|
||||
return toJSONSerializedString(result, log);
|
||||
} else {
|
||||
return toXMLSerializedString(result, log);
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,51 +83,65 @@ public class ApiResponseSerializer {
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String toJSONSerializedString(ResponseObject result) {
|
||||
if (result != null) {
|
||||
Gson gson = ApiResponseGsonHelper.getBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create();
|
||||
public static String toJSONSerializedString(ResponseObject result, StringBuilder log) {
|
||||
if (result != null && log != null) {
|
||||
Gson responseBuilder = ApiResponseGsonHelper.getBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create();
|
||||
Gson logBuilder = ApiResponseGsonHelper.getLogBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("{\"").append(result.getResponseName()).append("\":");
|
||||
log.append("{\"").append(result.getResponseName()).append("\":");
|
||||
if (result instanceof ListResponse) {
|
||||
List<? extends ResponseObject> responses = ((ListResponse)result).getResponses();
|
||||
Integer count = ((ListResponse)result).getCount();
|
||||
boolean nonZeroCount = (count != null && count.longValue() != 0);
|
||||
if (nonZeroCount) {
|
||||
sb.append("{\"").append(ApiConstants.COUNT).append("\":").append(count);
|
||||
log.append("{\"").append(ApiConstants.COUNT).append("\":").append(count);
|
||||
}
|
||||
|
||||
if ((responses != null) && !responses.isEmpty()) {
|
||||
String jsonStr = gson.toJson(responses.get(0));
|
||||
String jsonStr = responseBuilder.toJson(responses.get(0));
|
||||
jsonStr = unescape(jsonStr);
|
||||
String logStr = logBuilder.toJson(responses.get(0));
|
||||
logStr = unescape(logStr);
|
||||
|
||||
if (nonZeroCount) {
|
||||
sb.append(",\"").append(responses.get(0).getObjectName()).append("\":[").append(jsonStr);
|
||||
log.append(",\"").append(responses.get(0).getObjectName()).append("\":[").append(logStr);
|
||||
}
|
||||
|
||||
for (int i = 1; i < ((ListResponse)result).getResponses().size(); i++) {
|
||||
jsonStr = gson.toJson(responses.get(i));
|
||||
jsonStr = responseBuilder.toJson(responses.get(i));
|
||||
jsonStr = unescape(jsonStr);
|
||||
logStr = logBuilder.toJson(responses.get(i));
|
||||
logStr = unescape(logStr);
|
||||
sb.append(",").append(jsonStr);
|
||||
log.append(",").append(logStr);
|
||||
}
|
||||
sb.append("]}");
|
||||
log.append("]}");
|
||||
} else {
|
||||
if (!nonZeroCount) {
|
||||
sb.append("{");
|
||||
log.append("{");
|
||||
}
|
||||
|
||||
sb.append("}");
|
||||
log.append("}");
|
||||
}
|
||||
} else if (result instanceof SuccessResponse) {
|
||||
sb.append("{\"success\":\"").append(((SuccessResponse)result).getSuccess()).append("\"}");
|
||||
log.append("{\"success\":\"").append(((SuccessResponse)result).getSuccess()).append("\"}");
|
||||
} else if (result instanceof ExceptionResponse) {
|
||||
String jsonErrorText = gson.toJson(result);
|
||||
String jsonErrorText = responseBuilder.toJson(result);
|
||||
jsonErrorText = unescape(jsonErrorText);
|
||||
sb.append(jsonErrorText);
|
||||
log.append(jsonErrorText);
|
||||
} else {
|
||||
String jsonStr = gson.toJson(result);
|
||||
if ((jsonStr != null) && !"".equals(jsonStr)) {
|
||||
String jsonStr = responseBuilder.toJson(result);
|
||||
if (jsonStr != null && !jsonStr.isEmpty()) {
|
||||
jsonStr = unescape(jsonStr);
|
||||
if (result instanceof AsyncJobResponse || result instanceof CreateCmdResponse || result instanceof AuthenticationCmdResponse) {
|
||||
sb.append(jsonStr);
|
||||
@ -127,53 +151,74 @@ public class ApiResponseSerializer {
|
||||
} else {
|
||||
sb.append("{}");
|
||||
}
|
||||
String logStr = logBuilder.toJson(result);
|
||||
if (logStr != null && !logStr.isEmpty()) {
|
||||
logStr = unescape(logStr);
|
||||
if (result instanceof AsyncJobResponse || result instanceof CreateCmdResponse || result instanceof AuthenticationCmdResponse) {
|
||||
log.append(logStr);
|
||||
} else {
|
||||
log.append("{\"").append(result.getObjectName()).append("\":").append(logStr).append("}");
|
||||
}
|
||||
} else {
|
||||
log.append("{}");
|
||||
}
|
||||
}
|
||||
sb.append("}");
|
||||
log.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String toXMLSerializedString(ResponseObject result) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
sb.append("<").append(result.getResponseName()).append(" cloud-stack-version=\"").append(ApiDBUtils.getVersion()).append("\">");
|
||||
private static String toXMLSerializedString(ResponseObject result, StringBuilder log) {
|
||||
if (result != null && log != null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
sb.append("<").append(result.getResponseName()).append(" cloud-stack-version=\"").append(ApiDBUtils.getVersion()).append("\">");
|
||||
log.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
log.append("<").append(result.getResponseName()).append(" cloud-stack-version=\"").append(ApiDBUtils.getVersion()).append("\">");
|
||||
|
||||
if (result instanceof ListResponse) {
|
||||
Integer count = ((ListResponse)result).getCount();
|
||||
if (result instanceof ListResponse) {
|
||||
Integer count = ((ListResponse)result).getCount();
|
||||
|
||||
if (count != null && count != 0) {
|
||||
sb.append("<").append(ApiConstants.COUNT).append(">").append(((ListResponse)result).getCount()).append("</").append(ApiConstants.COUNT).append(">");
|
||||
}
|
||||
List<? extends ResponseObject> responses = ((ListResponse)result).getResponses();
|
||||
if ((responses != null) && !responses.isEmpty()) {
|
||||
for (ResponseObject obj : responses) {
|
||||
serializeResponseObjXML(sb, obj);
|
||||
if (count != null && count != 0) {
|
||||
sb.append("<").append(ApiConstants.COUNT).append(">").append(((ListResponse)result).getCount()).append("</").append(ApiConstants.COUNT).append(">");
|
||||
log.append("<").append(ApiConstants.COUNT).append(">").append(((ListResponse)result).getCount()).append("</").append(ApiConstants.COUNT).append(">");
|
||||
}
|
||||
List<? extends ResponseObject> responses = ((ListResponse)result).getResponses();
|
||||
if ((responses != null) && !responses.isEmpty()) {
|
||||
for (ResponseObject obj : responses) {
|
||||
serializeResponseObjXML(sb, log, obj);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (result instanceof CreateCmdResponse || result instanceof AsyncJobResponse || result instanceof AuthenticationCmdResponse) {
|
||||
serializeResponseObjFieldsXML(sb, log, result);
|
||||
} else {
|
||||
serializeResponseObjXML(sb, log, result);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (result instanceof CreateCmdResponse || result instanceof AsyncJobResponse || result instanceof AuthenticationCmdResponse) {
|
||||
serializeResponseObjFieldsXML(sb, result);
|
||||
} else {
|
||||
serializeResponseObjXML(sb, result);
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("</").append(result.getResponseName()).append(">");
|
||||
return sb.toString();
|
||||
sb.append("</").append(result.getResponseName()).append(">");
|
||||
log.append("</").append(result.getResponseName()).append(">");
|
||||
return sb.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void serializeResponseObjXML(StringBuilder sb, ResponseObject obj) {
|
||||
private static void serializeResponseObjXML(StringBuilder sb, StringBuilder log, ResponseObject obj) {
|
||||
if (!(obj instanceof SuccessResponse) && !(obj instanceof ExceptionResponse)) {
|
||||
sb.append("<").append(obj.getObjectName()).append(">");
|
||||
log.append("<").append(obj.getObjectName()).append(">");
|
||||
}
|
||||
serializeResponseObjFieldsXML(sb, obj);
|
||||
serializeResponseObjFieldsXML(sb, log, obj);
|
||||
if (!(obj instanceof SuccessResponse) && !(obj instanceof ExceptionResponse)) {
|
||||
sb.append("</").append(obj.getObjectName()).append(">");
|
||||
log.append("</").append(obj.getObjectName()).append(">");
|
||||
}
|
||||
}
|
||||
|
||||
public static Field[] getFlattenFields(Class<?> clz) {
|
||||
private static Field[] getFlattenFields(Class<?> clz) {
|
||||
List<Field> fields = new ArrayList<Field>();
|
||||
fields.addAll(Arrays.asList(clz.getDeclaredFields()));
|
||||
if (clz.getSuperclass() != null) {
|
||||
@ -182,24 +227,23 @@ public class ApiResponseSerializer {
|
||||
return fields.toArray(new Field[] {});
|
||||
}
|
||||
|
||||
private static void serializeResponseObjFieldsXML(StringBuilder sb, ResponseObject obj) {
|
||||
private static void serializeResponseObjFieldsXML(StringBuilder sb, StringBuilder log, ResponseObject obj) {
|
||||
boolean isAsync = false;
|
||||
if (obj instanceof AsyncJobResponse)
|
||||
isAsync = true;
|
||||
|
||||
//Field[] fields = obj.getClass().getDeclaredFields();
|
||||
Field[] fields = getFlattenFields(obj.getClass());
|
||||
for (Field field : fields) {
|
||||
if ((field.getModifiers() & Modifier.TRANSIENT) != 0) {
|
||||
continue; // skip transient fields
|
||||
}
|
||||
|
||||
|
||||
SerializedName serializedName = field.getAnnotation(SerializedName.class);
|
||||
if (serializedName == null) {
|
||||
continue; // skip fields w/o serialized name
|
||||
}
|
||||
|
||||
boolean logField = true;
|
||||
Param param = field.getAnnotation(Param.class);
|
||||
if (param != null) {
|
||||
RoleType[] allowedRoles = param.authorized();
|
||||
@ -213,10 +257,13 @@ public class ApiResponseSerializer {
|
||||
}
|
||||
}
|
||||
if (!permittedParameter) {
|
||||
s_logger.trace("Ignoring paremeter " + param.name() + " as the caller is not authorized to see it");
|
||||
s_logger.trace("Ignoring parameter " + param.name() + " as the caller is not authorized to see it");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (param.isSensitive()) {
|
||||
logField = false;
|
||||
}
|
||||
}
|
||||
|
||||
field.setAccessible(true);
|
||||
@ -233,10 +280,12 @@ public class ApiResponseSerializer {
|
||||
ResponseObject subObj = (ResponseObject)fieldValue;
|
||||
if (isAsync) {
|
||||
sb.append("<jobresult>");
|
||||
log.append("<jobresult>");
|
||||
}
|
||||
serializeResponseObjXML(sb, subObj);
|
||||
serializeResponseObjXML(sb, log, subObj);
|
||||
if (isAsync) {
|
||||
sb.append("</jobresult>");
|
||||
log.append("</jobresult>");
|
||||
}
|
||||
} else if (fieldValue instanceof Collection<?>) {
|
||||
Collection<?> subResponseList = (Collection<?>)fieldValue;
|
||||
@ -247,7 +296,7 @@ public class ApiResponseSerializer {
|
||||
if (serializedName != null) {
|
||||
subObj.setObjectName(serializedName.value());
|
||||
}
|
||||
serializeResponseObjXML(sb, subObj);
|
||||
serializeResponseObjXML(sb, log, subObj);
|
||||
} else if (value instanceof ExceptionProxyObject) {
|
||||
// Only exception reponses carry a list of
|
||||
// ExceptionProxyObject objects.
|
||||
@ -256,30 +305,32 @@ public class ApiResponseSerializer {
|
||||
// encountered, put in a uuidList tag.
|
||||
if (!usedUuidList) {
|
||||
sb.append("<" + serializedName.value() + ">");
|
||||
log.append("<" + serializedName.value() + ">");
|
||||
usedUuidList = true;
|
||||
}
|
||||
sb.append("<" + "uuid" + ">" + idProxy.getUuid() + "</" + "uuid" + ">");
|
||||
log.append("<" + "uuid" + ">" + idProxy.getUuid() + "</" + "uuid" + ">");
|
||||
// Append the new descriptive property also.
|
||||
String idFieldName = idProxy.getDescription();
|
||||
if (idFieldName != null) {
|
||||
sb.append("<" + "uuidProperty" + ">" + idFieldName + "</" + "uuidProperty" + ">");
|
||||
log.append("<" + "uuidProperty" + ">" + idFieldName + "</" + "uuidProperty" + ">");
|
||||
}
|
||||
} else if (value instanceof String) {
|
||||
sb.append("<").append(serializedName.value()).append(">").append(value).append("</").append(serializedName.value()).append(">");
|
||||
if (logField) {
|
||||
log.append("<").append(serializedName.value()).append(">").append(value).append("</").append(serializedName.value()).append(">");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (usedUuidList) {
|
||||
// close the uuidList.
|
||||
sb.append("</").append(serializedName.value()).append(">");
|
||||
log.append("</").append(serializedName.value()).append(">");
|
||||
}
|
||||
} else if (fieldValue instanceof Date) {
|
||||
sb.append("<")
|
||||
.append(serializedName.value())
|
||||
.append(">")
|
||||
.append(BaseCmd.getDateString((Date)fieldValue))
|
||||
.append("</")
|
||||
.append(serializedName.value())
|
||||
.append(">");
|
||||
sb.append("<").append(serializedName.value()).append(">").append(BaseCmd.getDateString((Date)fieldValue)).append("</").append(serializedName.value()).append(">");
|
||||
log.append("<").append(serializedName.value()).append(">").append(BaseCmd.getDateString((Date)fieldValue)).append("</").append(serializedName.value()).append(">");
|
||||
} else {
|
||||
String resultString = escapeSpecialXmlChars(fieldValue.toString());
|
||||
if (!(obj instanceof ExceptionResponse)) {
|
||||
@ -287,6 +338,9 @@ public class ApiResponseSerializer {
|
||||
}
|
||||
|
||||
sb.append("<").append(serializedName.value()).append(">").append(resultString).append("</").append(serializedName.value()).append(">");
|
||||
if (logField) {
|
||||
log.append("<").append(serializedName.value()).append(">").append(resultString).append("</").append(serializedName.value()).append(">");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user