mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-11-04 00:02:37 +01:00 
			
		
		
		
	Merge pull request #1021 from koushik-das/CLOUDSTACK-8485
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 annotation (@LogLevel(Log4jLevel.Off)) to sensitive response object fields Ran the following tests on simulator: test_vm_life_cycle.py Test advanced zone virtual router ... === TestName: test_advZoneVirtualRouter | Status : SUCCESS === ok Test Deploy Virtual Machine ... === TestName: test_deploy_vm | Status : SUCCESS === ok Test Multiple Deploy Virtual Machine ... === TestName: test_deploy_vm_multiple | Status : SUCCESS === ok Test Stop Virtual Machine ... === TestName: test_01_stop_vm | Status : SUCCESS === ok Test Start Virtual Machine ... === TestName: test_02_start_vm | Status : SUCCESS === ok Test Reboot Virtual Machine ... === TestName: test_03_reboot_vm | Status : SUCCESS === ok Test destroy Virtual Machine ... === TestName: test_06_destroy_vm | Status : SUCCESS === ok Test recover Virtual Machine ... === TestName: test_07_restore_vm | Status : SUCCESS === ok Test migrate VM ... === TestName: test_08_migrate_vm | Status : SUCCESS === ok Test destroy(expunge) Virtual Machine ... === TestName: test_09_expunge_vm | Status : SUCCESS === ok ---------------------------------------------------------------------- Ran 10 tests in 306.429s OK test_volumes.py Download a Volume attached to a VM ... === TestName: test_03_download_attached_volume | Status : SUCCESS === ok Delete a Volume attached to a VM ... === TestName: test_04_delete_attached_volume | Status : SUCCESS === ok Detach a Volume attached to a VM ... === TestName: test_05_detach_volume | Status : SUCCESS === ok Delete a Volume unattached to an VM ... === TestName: test_09_delete_detached_volume | Status : SUCCESS === ok ---------------------------------------------------------------------- Ran 4 tests in 184.132s OK test_network.py Test for delete account ... === TestName: test_delete_account | Status : SUCCESS === ok Test for Associate/Disassociate public IP address for admin account ... === TestName: test_public_ip_admin_account | Status : SUCCESS === ok Test for Associate/Disassociate public IP address for user account ... === TestName: test_public_ip_user_account | Status : SUCCESS === ok Test for release public IP address ... === TestName: test_releaseIP | Status : SUCCESS === ok ---------------------------------------------------------------------- Ran 4 tests in 783.726s OK test_routers.py Test router internal advanced zone ... SKIP: Marvin configuration has no host credentials to check router services Test restart network ... === TestName: test_03_restart_network_cleanup | Status : SUCCESS === ok Test router basic setup ... === TestName: test_05_router_basic | Status : SUCCESS === ok Test router advanced setup ... === TestName: test_06_router_advanced | Status : SUCCESS === ok Test stop router ... === TestName: test_07_stop_router | Status : SUCCESS === ok Test start router ... === TestName: test_08_start_router | Status : SUCCESS === ok Test reboot router ... === TestName: test_09_reboot_router | Status : SUCCESS === ok ---------------------------------------------------------------------- Ran 7 tests in 42.958s OK (SKIP=1) test_global_settings.py test update configuration setting at zone level scope ... === TestName: test_UpdateConfigParamWithScope | Status : SUCCESS === ok ---------------------------------------------------------------------- Ran 1 test in 0.127s OK test_resource_detail.py Test volume detail ... === TestName: test_01_updatevolumedetail | Status : SUCCESS === ok ---------------------------------------------------------------------- Ran 1 test in 11.492s OK * pr/1021: 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 Signed-off-by: Remi Bergsma <github@remi.nl>
This commit is contained in:
		
						commit
						a2a72887d2
					
				@ -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) {
 | 
			
		||||
    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 (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, obj);
 | 
			
		||||
                        serializeResponseObjXML(sb, log, obj);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                if (result instanceof CreateCmdResponse || result instanceof AsyncJobResponse || result instanceof AuthenticationCmdResponse) {
 | 
			
		||||
                serializeResponseObjFieldsXML(sb, result);
 | 
			
		||||
                    serializeResponseObjFieldsXML(sb, log, result);
 | 
			
		||||
                } else {
 | 
			
		||||
                serializeResponseObjXML(sb, result);
 | 
			
		||||
                    serializeResponseObjXML(sb, log, result);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            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