mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
- CLOUDSTACK-3229: Properly serialize the https property to the s3Xen
plugin
- Extracts the duplicated serializeProperties methods to
ReflectUtils#flattenProperties
- Adds unit tests for ReflectUtils#flattenProperties
This commit is contained in:
parent
51e4f597e0
commit
1ae682de78
@ -16,92 +16,6 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.hypervisor.xen.resource;
|
package com.cloud.hypervisor.xen.resource;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
|
|
||||||
import java.beans.BeanInfo;
|
|
||||||
import java.beans.IntrospectionException;
|
|
||||||
import java.beans.Introspector;
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import javax.ejb.Local;
|
|
||||||
import javax.naming.ConfigurationException;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
|
|
||||||
import com.cloud.agent.api.to.DhcpTO;
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import org.apache.xmlrpc.XmlRpcException;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
import org.w3c.dom.NodeList;
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
|
|
||||||
import com.trilead.ssh2.SCPClient;
|
|
||||||
import com.xensource.xenapi.Bond;
|
|
||||||
import com.xensource.xenapi.Connection;
|
|
||||||
import com.xensource.xenapi.Console;
|
|
||||||
import com.xensource.xenapi.Host;
|
|
||||||
import com.xensource.xenapi.HostCpu;
|
|
||||||
import com.xensource.xenapi.HostMetrics;
|
|
||||||
import com.xensource.xenapi.Network;
|
|
||||||
import com.xensource.xenapi.PBD;
|
|
||||||
import com.xensource.xenapi.PIF;
|
|
||||||
import com.xensource.xenapi.PIF.Record;
|
|
||||||
import com.xensource.xenapi.Pool;
|
|
||||||
import com.xensource.xenapi.SR;
|
|
||||||
import com.xensource.xenapi.Session;
|
|
||||||
import com.xensource.xenapi.Task;
|
|
||||||
import com.xensource.xenapi.Types;
|
|
||||||
import com.xensource.xenapi.Types.BadAsyncResult;
|
|
||||||
import com.xensource.xenapi.Types.BadServerResponse;
|
|
||||||
import com.xensource.xenapi.Types.ConsoleProtocol;
|
|
||||||
import com.xensource.xenapi.Types.IpConfigurationMode;
|
|
||||||
import com.xensource.xenapi.Types.OperationNotAllowed;
|
|
||||||
import com.xensource.xenapi.Types.SrFull;
|
|
||||||
import com.xensource.xenapi.Types.VbdType;
|
|
||||||
import com.xensource.xenapi.Types.VmBadPowerState;
|
|
||||||
import com.xensource.xenapi.Types.VmPowerState;
|
|
||||||
import com.xensource.xenapi.Types.XenAPIException;
|
|
||||||
import com.xensource.xenapi.VBD;
|
|
||||||
import com.xensource.xenapi.VBDMetrics;
|
|
||||||
import com.xensource.xenapi.VDI;
|
|
||||||
import com.xensource.xenapi.VIF;
|
|
||||||
import com.xensource.xenapi.VLAN;
|
|
||||||
import com.xensource.xenapi.VM;
|
|
||||||
import com.xensource.xenapi.VMGuestMetrics;
|
|
||||||
import com.xensource.xenapi.XenAPIObject;
|
|
||||||
|
|
||||||
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
|
||||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
|
||||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
|
||||||
|
|
||||||
import com.cloud.agent.IAgentControl;
|
import com.cloud.agent.IAgentControl;
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
import com.cloud.agent.api.AttachIsoCommand;
|
import com.cloud.agent.api.AttachIsoCommand;
|
||||||
@ -242,6 +156,7 @@ import com.cloud.agent.api.storage.ResizeVolumeAnswer;
|
|||||||
import com.cloud.agent.api.storage.ResizeVolumeCommand;
|
import com.cloud.agent.api.storage.ResizeVolumeCommand;
|
||||||
import com.cloud.agent.api.to.DataStoreTO;
|
import com.cloud.agent.api.to.DataStoreTO;
|
||||||
import com.cloud.agent.api.to.DataTO;
|
import com.cloud.agent.api.to.DataTO;
|
||||||
|
import com.cloud.agent.api.to.DhcpTO;
|
||||||
import com.cloud.agent.api.to.DiskTO;
|
import com.cloud.agent.api.to.DiskTO;
|
||||||
import com.cloud.agent.api.to.FirewallRuleTO;
|
import com.cloud.agent.api.to.FirewallRuleTO;
|
||||||
import com.cloud.agent.api.to.IpAddressTO;
|
import com.cloud.agent.api.to.IpAddressTO;
|
||||||
@ -299,6 +214,82 @@ import com.cloud.vm.DiskProfile;
|
|||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
import com.cloud.vm.VirtualMachine.State;
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
import com.cloud.vm.snapshot.VMSnapshot;
|
import com.cloud.vm.snapshot.VMSnapshot;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.trilead.ssh2.SCPClient;
|
||||||
|
import com.xensource.xenapi.Bond;
|
||||||
|
import com.xensource.xenapi.Connection;
|
||||||
|
import com.xensource.xenapi.Console;
|
||||||
|
import com.xensource.xenapi.Host;
|
||||||
|
import com.xensource.xenapi.HostCpu;
|
||||||
|
import com.xensource.xenapi.HostMetrics;
|
||||||
|
import com.xensource.xenapi.Network;
|
||||||
|
import com.xensource.xenapi.PBD;
|
||||||
|
import com.xensource.xenapi.PIF;
|
||||||
|
import com.xensource.xenapi.PIF.Record;
|
||||||
|
import com.xensource.xenapi.Pool;
|
||||||
|
import com.xensource.xenapi.SR;
|
||||||
|
import com.xensource.xenapi.Session;
|
||||||
|
import com.xensource.xenapi.Task;
|
||||||
|
import com.xensource.xenapi.Types;
|
||||||
|
import com.xensource.xenapi.Types.BadAsyncResult;
|
||||||
|
import com.xensource.xenapi.Types.BadServerResponse;
|
||||||
|
import com.xensource.xenapi.Types.ConsoleProtocol;
|
||||||
|
import com.xensource.xenapi.Types.IpConfigurationMode;
|
||||||
|
import com.xensource.xenapi.Types.OperationNotAllowed;
|
||||||
|
import com.xensource.xenapi.Types.SrFull;
|
||||||
|
import com.xensource.xenapi.Types.VbdType;
|
||||||
|
import com.xensource.xenapi.Types.VmBadPowerState;
|
||||||
|
import com.xensource.xenapi.Types.VmPowerState;
|
||||||
|
import com.xensource.xenapi.Types.XenAPIException;
|
||||||
|
import com.xensource.xenapi.VBD;
|
||||||
|
import com.xensource.xenapi.VBDMetrics;
|
||||||
|
import com.xensource.xenapi.VDI;
|
||||||
|
import com.xensource.xenapi.VIF;
|
||||||
|
import com.xensource.xenapi.VLAN;
|
||||||
|
import com.xensource.xenapi.VM;
|
||||||
|
import com.xensource.xenapi.VMGuestMetrics;
|
||||||
|
import com.xensource.xenapi.XenAPIObject;
|
||||||
|
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||||
|
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.apache.xmlrpc.XmlRpcException;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static com.cloud.utils.ReflectUtil.flattenProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CitrixResourceBase encapsulates the calls to the XenServer Xapi process
|
* CitrixResourceBase encapsulates the calls to the XenServer Xapi process
|
||||||
@ -7401,53 +7392,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
return new BackupSnapshotAnswer(cmd, success, details, snapshotBackupUuid, fullbackup);
|
return new BackupSnapshotAnswer(cmd, success, details, snapshotBackupUuid, fullbackup);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> serializeProperties(final Object object,
|
|
||||||
final Class<?> propertySet) {
|
|
||||||
|
|
||||||
assert object != null;
|
|
||||||
assert propertySet != null;
|
|
||||||
assert propertySet.isAssignableFrom(object.getClass());
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
final BeanInfo beanInfo = Introspector.getBeanInfo(propertySet);
|
|
||||||
final PropertyDescriptor[] descriptors = beanInfo
|
|
||||||
.getPropertyDescriptors();
|
|
||||||
|
|
||||||
final List<String> serializedProperties = new ArrayList<String>();
|
|
||||||
for (final PropertyDescriptor descriptor : descriptors) {
|
|
||||||
|
|
||||||
serializedProperties.add(descriptor.getName());
|
|
||||||
final Object value = descriptor.getReadMethod().invoke(object);
|
|
||||||
serializedProperties.add(value != null ? value.toString()
|
|
||||||
: "null");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.unmodifiableList(serializedProperties);
|
|
||||||
|
|
||||||
} catch (IntrospectionException e) {
|
|
||||||
s_logger.warn(
|
|
||||||
"Ignored IntrospectionException when serializing class "
|
|
||||||
+ object.getClass().getCanonicalName(), e);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
s_logger.warn(
|
|
||||||
"Ignored IllegalArgumentException when serializing class "
|
|
||||||
+ object.getClass().getCanonicalName(), e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
s_logger.warn(
|
|
||||||
"Ignored IllegalAccessException when serializing class "
|
|
||||||
+ object.getClass().getCanonicalName(), e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
s_logger.warn(
|
|
||||||
"Ignored InvocationTargetException when serializing class "
|
|
||||||
+ object.getClass().getCanonicalName(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.emptyList();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean backupSnapshotToS3(final Connection connection,
|
private boolean backupSnapshotToS3(final Connection connection,
|
||||||
final S3TO s3, final String srUuid, final String snapshotUuid,
|
final S3TO s3, final String srUuid, final String snapshotUuid,
|
||||||
final Boolean iSCSIFlag, final int wait) {
|
final Boolean iSCSIFlag, final int wait) {
|
||||||
@ -7460,8 +7404,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
final List<String> parameters = new ArrayList<String>(
|
final List<String> parameters = flattenProperties(s3,
|
||||||
serializeProperties(s3, S3Utils.ClientOptions.class));
|
S3Utils.ClientOptions.class);
|
||||||
parameters.addAll(Arrays.asList("operation", "put", "directory",
|
parameters.addAll(Arrays.asList("operation", "put", "directory",
|
||||||
dir, "filename", filename, "iSCSIFlag",
|
dir, "filename", filename, "iSCSIFlag",
|
||||||
iSCSIFlag.toString(), "bucket", s3.getBucketName(), "key", key));
|
iSCSIFlag.toString(), "bucket", s3.getBucketName(), "key", key));
|
||||||
|
|||||||
@ -71,22 +71,17 @@ import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
|||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.apache.xmlrpc.XmlRpcException;
|
import org.apache.xmlrpc.XmlRpcException;
|
||||||
|
|
||||||
import java.beans.BeanInfo;
|
|
||||||
import java.beans.IntrospectionException;
|
|
||||||
import java.beans.Introspector;
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static com.cloud.utils.ReflectUtil.flattenProperties;
|
||||||
|
|
||||||
public class XenServerStorageProcessor implements StorageProcessor {
|
public class XenServerStorageProcessor implements StorageProcessor {
|
||||||
private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class);
|
private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class);
|
||||||
protected CitrixResourceBase hypervisorResource;
|
protected CitrixResourceBase hypervisorResource;
|
||||||
@ -1066,53 +1061,6 @@ public class XenServerStorageProcessor implements StorageProcessor {
|
|||||||
return lfilename;
|
return lfilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> serializeProperties(final Object object,
|
|
||||||
final Class<?> propertySet) {
|
|
||||||
|
|
||||||
assert object != null;
|
|
||||||
assert propertySet != null;
|
|
||||||
assert propertySet.isAssignableFrom(object.getClass());
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
final BeanInfo beanInfo = Introspector.getBeanInfo(propertySet);
|
|
||||||
final PropertyDescriptor[] descriptors = beanInfo
|
|
||||||
.getPropertyDescriptors();
|
|
||||||
|
|
||||||
final List<String> serializedProperties = new ArrayList<String>();
|
|
||||||
for (final PropertyDescriptor descriptor : descriptors) {
|
|
||||||
|
|
||||||
serializedProperties.add(descriptor.getName());
|
|
||||||
final Object value = descriptor.getReadMethod().invoke(object);
|
|
||||||
serializedProperties.add(value != null ? value.toString()
|
|
||||||
: "null");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.unmodifiableList(serializedProperties);
|
|
||||||
|
|
||||||
} catch (IntrospectionException e) {
|
|
||||||
s_logger.warn(
|
|
||||||
"Ignored IntrospectionException when serializing class "
|
|
||||||
+ object.getClass().getCanonicalName(), e);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
s_logger.warn(
|
|
||||||
"Ignored IllegalArgumentException when serializing class "
|
|
||||||
+ object.getClass().getCanonicalName(), e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
s_logger.warn(
|
|
||||||
"Ignored IllegalAccessException when serializing class "
|
|
||||||
+ object.getClass().getCanonicalName(), e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
s_logger.warn(
|
|
||||||
"Ignored InvocationTargetException when serializing class "
|
|
||||||
+ object.getClass().getCanonicalName(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.emptyList();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean backupSnapshotToS3(final Connection connection,
|
private boolean backupSnapshotToS3(final Connection connection,
|
||||||
final S3TO s3, final String srUuid, final String snapshotUuid,
|
final S3TO s3, final String srUuid, final String snapshotUuid,
|
||||||
final Boolean iSCSIFlag, final int wait) {
|
final Boolean iSCSIFlag, final int wait) {
|
||||||
@ -1125,8 +1073,8 @@ public class XenServerStorageProcessor implements StorageProcessor {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
final List<String> parameters = new ArrayList<String>(
|
final List<String> parameters = flattenProperties(s3,
|
||||||
serializeProperties(s3, S3Utils.ClientOptions.class));
|
S3Utils.ClientOptions.class);
|
||||||
parameters.addAll(Arrays.asList("operation", "put", "directory",
|
parameters.addAll(Arrays.asList("operation", "put", "directory",
|
||||||
dir, "filename", filename, "iSCSIFlag",
|
dir, "filename", filename, "iSCSIFlag",
|
||||||
iSCSIFlag.toString(), "bucket", s3.getBucketName(), "key", key));
|
iSCSIFlag.toString(), "bucket", s3.getBucketName(), "key", key));
|
||||||
|
|||||||
@ -306,7 +306,7 @@ def parseArguments(args):
|
|||||||
# the com.cloud.utils.S3Utils#ClientOptions interface
|
# the com.cloud.utils.S3Utils#ClientOptions interface
|
||||||
client = S3Client(
|
client = S3Client(
|
||||||
args['accessKey'], args['secretKey'], args['endPoint'],
|
args['accessKey'], args['secretKey'], args['endPoint'],
|
||||||
args['isHttps'], args['connectionTimeout'], args['socketTimeout'])
|
args['https'], args['connectionTimeout'], args['socketTimeout'])
|
||||||
|
|
||||||
operation = args['operation']
|
operation = args['operation']
|
||||||
bucket = args['bucket']
|
bucket = args['bucket']
|
||||||
|
|||||||
@ -16,8 +16,17 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.utils;
|
package com.cloud.utils;
|
||||||
|
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
|
import java.beans.BeanInfo;
|
||||||
|
import java.beans.IntrospectionException;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -25,10 +34,14 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import static java.beans.Introspector.getBeanInfo;
|
||||||
import org.reflections.Reflections;
|
import static java.util.Collections.emptyList;
|
||||||
|
import static java.util.Collections.unmodifiableList;
|
||||||
|
|
||||||
public class ReflectUtil {
|
public class ReflectUtil {
|
||||||
|
|
||||||
|
private static final Logger s_logger = Logger.getLogger(ReflectUtil.class);
|
||||||
|
|
||||||
public static Pair<Class<?>, Field> getAnyField(Class<?> clazz, String fieldName) {
|
public static Pair<Class<?>, Field> getAnyField(Class<?> clazz, String fieldName) {
|
||||||
try {
|
try {
|
||||||
return new Pair<Class<?>, Field>(clazz, clazz.getDeclaredField(fieldName));
|
return new Pair<Class<?>, Field>(clazz, clazz.getDeclaredField(fieldName));
|
||||||
@ -129,4 +142,75 @@ public class ReflectUtil {
|
|||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<String> flattenProperties(final Object target,
|
||||||
|
final Class<?> clazz) {
|
||||||
|
return flattenPropeties(target, clazz, "class");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> flattenPropeties(final Object target,
|
||||||
|
final Class<?> clazz,
|
||||||
|
final String...
|
||||||
|
excludedProperties) {
|
||||||
|
return flattenProperties(target, clazz,
|
||||||
|
ImmutableSet.copyOf(excludedProperties));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> flattenProperties(final Object target,
|
||||||
|
final Class<?> clazz,
|
||||||
|
final ImmutableSet<String>
|
||||||
|
excludedProperties) {
|
||||||
|
|
||||||
|
assert clazz != null;
|
||||||
|
|
||||||
|
if (target == null) {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert clazz.isAssignableFrom(target.getClass());
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
final BeanInfo beanInfo = getBeanInfo(clazz);
|
||||||
|
final PropertyDescriptor[] descriptors = beanInfo
|
||||||
|
.getPropertyDescriptors();
|
||||||
|
|
||||||
|
final List<String> serializedProperties = new ArrayList<String>();
|
||||||
|
for (final PropertyDescriptor descriptor : descriptors) {
|
||||||
|
|
||||||
|
if (excludedProperties.contains(descriptor.getName())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
serializedProperties.add(descriptor.getName());
|
||||||
|
final Object value = descriptor.getReadMethod().invoke(target);
|
||||||
|
serializedProperties.add(value != null ? value.toString()
|
||||||
|
: "null");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return unmodifiableList(serializedProperties);
|
||||||
|
|
||||||
|
} catch (IntrospectionException e) {
|
||||||
|
s_logger.warn(
|
||||||
|
"Ignored IntrospectionException when serializing class "
|
||||||
|
+ target.getClass().getCanonicalName(), e);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
s_logger.warn(
|
||||||
|
"Ignored IllegalArgumentException when serializing class "
|
||||||
|
+ target.getClass().getCanonicalName(), e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
s_logger.warn(
|
||||||
|
"Ignored IllegalAccessException when serializing class "
|
||||||
|
+ target.getClass().getCanonicalName(), e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
s_logger.warn(
|
||||||
|
"Ignored InvocationTargetException when serializing class "
|
||||||
|
+ target.getClass().getCanonicalName(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return emptyList();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
91
utils/test/com/cloud/utils/ReflectUtilTest.java
Normal file
91
utils/test/com/cloud/utils/ReflectUtilTest.java
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// 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
|
||||||
|
// 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 com.cloud.utils;
|
||||||
|
package com.cloud.utils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static com.cloud.utils.ReflectUtil.flattenProperties;
|
||||||
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
|
import static java.lang.Boolean.TRUE;
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public final class ReflectUtilTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFlattenNonNullProperties() throws Exception {
|
||||||
|
|
||||||
|
final List<String> expectedResult = newArrayList("booleanProperty",
|
||||||
|
TRUE.toString(), "intProperty", "1",
|
||||||
|
"stringProperty", "foo");
|
||||||
|
|
||||||
|
final Bean bean = new Bean(1, true, "foo");
|
||||||
|
|
||||||
|
assertEquals(expectedResult, flattenProperties(bean, Bean.class));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFlattenNullProperties() throws Exception {
|
||||||
|
|
||||||
|
final List<String> expectedResult = newArrayList("booleanProperty",
|
||||||
|
TRUE.toString(), "intProperty", "1",
|
||||||
|
"stringProperty", "null");
|
||||||
|
|
||||||
|
final Bean bean = new Bean(1, true, null);
|
||||||
|
|
||||||
|
assertEquals(expectedResult, flattenProperties(bean, Bean.class));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFlattenPropertiesNullTarget() throws Exception {
|
||||||
|
assertEquals(emptyList(), flattenProperties(null, Bean.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Bean {
|
||||||
|
|
||||||
|
private final int intProperty;
|
||||||
|
private final boolean booleanProperty;
|
||||||
|
private final String stringProperty;
|
||||||
|
|
||||||
|
private Bean(final int intProperty, final boolean booleanProperty,
|
||||||
|
final String stringProperty) {
|
||||||
|
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.intProperty = intProperty;
|
||||||
|
this.booleanProperty = booleanProperty;
|
||||||
|
this.stringProperty = stringProperty;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIntProperty() {
|
||||||
|
return intProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBooleanProperty() {
|
||||||
|
return booleanProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStringProperty() {
|
||||||
|
return stringProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user