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