All Downloads are FREE. Search and download functionalities are using the official Maven repository.

patterntesting.runtime.junit.SerializableTester Maven / Gradle / Ivy

Go to download

PatternTesting Runtime (patterntesting-rt) is the runtime component for the PatternTesting framework. It provides the annotations and base classes for the PatternTesting testing framework (e.g. patterntesting-check, patterntesting-concurrent or patterntesting-exception) but can be also used standalone for classpath monitoring or profiling. It uses AOP and AspectJ to perform this feat.

There is a newer version: 2.5.0
Show newest version
/*
 * (c)reated 21.07.2010 by oliver
 */
package patterntesting.runtime.junit;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;

import org.apache.logging.log4j.*;

import patterntesting.runtime.monitor.ClasspathMonitor;
import patterntesting.runtime.util.Converter;

/**
 * This is a utility class to check the serializable nature of classes.
 * 

* NOTE: In the future this class will be perhaps part of the ObjectTester * class. *

*

* Before v1.1 the methods are named "checkSerialization". Since 1.1 these * methods will have now an "assert" prefix ("assertSerialization"). *

* * @author oliver ([email protected]) * @since 1.0.3 (21.07.2010) */ public final class SerializableTester { private static final Logger LOG = LogManager.getLogger(SerializableTester.class); private static final ClasspathMonitor CLASSPATH_MONITOR = ClasspathMonitor.getInstance(); /** Utitlity class - no need to instantiate it. */ private SerializableTester() { } /** * Check serialization and deserialization of an object. Because not all * classes has a (correct) overwritten equals method we do not compare the * deserialized object with the equals() method. But if it implements * Comparable we verify the equality of the two objects with the compareTo() * method. * * @param object the object * @throws NotSerializableException if object can't serialized * @since 1.1 */ public static void assertSerialization(final Serializable object) throws NotSerializableException { Object deserialized = deserialize(object); if (object instanceof Comparable) { ObjectTester.assertCompareTo(object, deserialized); } assertNoFinalTransientAttribute(object.getClass()); } /** * Serialiazes and deserializes the given object. This can be used e.g. for * testing if you want to test the deserialized object if transient * attributes are initialized correct (transient attributes are null after * deserialization). *

* This method is a result of feature * request 50. *

* * @param object the object to serialize * @return the deserialized object * @throws NotSerializableException if serialization fails * @since 1.7.2 */ public static Serializable deserialize(final Serializable object) throws NotSerializableException { byte[] bytes = Converter.serialize(object); LOG.debug(object + " serialized in " + bytes.length + " bytes"); try { return Converter.deserialize(bytes); } catch (ClassNotFoundException canthappen) { throw new IllegalArgumentException("cannot be deserialized: " + object, canthappen); } } /** * This method will create an object of the given class using the default * constructor. So three preconditions must be true: *
    *
  1. the class must not be abstract
  2. *
  3. there must be a (public) default constructor
  4. *
  5. it must be Serializable
  6. *
* * @param clazz * the clazz * @throws NotSerializableException * if the check fails * @since 1.1 */ public static void assertSerialization(final Class clazz) throws NotSerializableException { if (LOG.isTraceEnabled()) { LOG.trace("checking " + clazz.getName() + " if it can be serialized..."); } Serializable obj = instantiate(clazz); assertSerialization(obj); } /** * Check for each class in the given collection if it can be serialized and * deserialized. * * @param classes * a collection of classes to be checked * @throws NotSerializableException * if one of the classes can't be serialized * @since 1.1 */ public static void assertSerialization(final Collection> classes) throws NotSerializableException { for (Class clazz : classes) { assertSerialization(clazz); } } /** * Check for each class in the given package if it can be serialized and * deserialized. *

* To get a name of a package call {@link Package#getPackage(String)}. But * be sure that you can't get null as result. In this case use * {@link #assertSerializationOfPackage(String)}. *

* * @param pkg * the package e.g. "patterntesting.runtime" * @throws NotSerializableException * if one of the class can't be serialized * @see #assertSerializationOfPackage(String) * @since 1.1 */ public static void assertSerialization(final Package pkg) throws NotSerializableException { assert pkg != null; assertSerializationOfPackage(pkg.getName()); } /** * Check for each class in the given package if it can be serialized and * deserialized. * * @param packageName * the package name e.g. "patterntesting.runtime" * @throws NotSerializableException * if one of the class can't be serialized * @since 1.1 */ public static void assertSerializationOfPackage(final String packageName) throws NotSerializableException { assert packageName != null; Collection> classes = getSerializableClasses(packageName); assertSerialization(classes); } @SuppressWarnings("unchecked") private static Collection> getSerializableClasses(final String packageName) { String[] classnames = CLASSPATH_MONITOR.getClasspathClasses(); Collection> classes = new ArrayList<>(); for (int i = 0; i < classnames.length; i++) { if (classnames[i].startsWith(packageName)) { try { Class clazz = Class.forName(classnames[i]); if (Serializable.class.isAssignableFrom(clazz)) { classes.add((Class) clazz); } } catch (ClassNotFoundException ignored) { LOG.debug("Class {} is ignored:", classnames[i], ignored); } catch (LinkageError ignored) { LOG.debug("Uninitializable class {} is ignored:", classnames[i], ignored); } } } return classes; } /** * Serializable classes must not have final transient attributes. Why? * Transient attributes are not stored when an object is serialized. And * if they are final they cannot be initialized after deserialization. * * @param clazz the serialiable class * @since 1.7.2 */ public static void assertNoFinalTransientAttribute(Class clazz) { for (Field field : clazz.getDeclaredFields()) { int mod = field.getModifiers(); if (Modifier.isFinal(mod) && Modifier.isTransient(mod)) { throw new AssertionError("transient trap - don't use transient and final together in: " + field); } } } /** * Gets the size of of a newly created object of the given clazz. This is * the is the number of bytes the created object needs for serialization. * * @param clazz the clazz * @return the size of * @since 1.5 (14.10.2014) */ public static int getSizeOf(final Class clazz) { Serializable obj = instantiate(clazz); return getSizeOf(obj); } /** * Gets the size of the given object - this is the number of bytes the given * object needs for serialization. * * @param object * the object * @return the size of * @since 1.5 (14.10.2014) */ public static int getSizeOf(final Serializable object) { try { return Converter.serialize(object).length; } catch (NotSerializableException ex) { throw new IllegalArgumentException("not serializable: " + object, ex); } } private static Serializable instantiate(final Class clazz) { try { return clazz.newInstance(); } catch (InstantiationException ex) { throw new IllegalArgumentException("can't instantiate " + clazz, ex); } catch (IllegalAccessException ex) { throw new IllegalArgumentException("can't access ctor of " + clazz, ex); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy