From 8e6ff8fe82827683ec14b55e3ac21bad6cd04ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sylvain=20Hall=C3=A9?= Date: Sat, 27 Apr 2019 06:24:27 -0400 Subject: [PATCH] Bugfixes to object printers; added RotePrintHandler --- .../src/ca/uqac/lif/azrael/ObjectPrinter.java | 20 +++++ .../src/ca/uqac/lif/azrael/ObjectReader.java | 61 ++++++++------ .../lif/azrael/ReflectionPrintHandler.java | 8 +- .../lif/azrael/fridge/SerializeFridge.java | 1 + .../azrael/size/CollectionPrintHandler.java | 13 ++- .../lif/azrael/size/NullPrintHandler.java | 41 ++++++++++ .../lif/azrael/size/RotePrintHandler.java | 80 +++++++++++++++++++ .../ca/uqac/lif/azrael/size/SizePrinter.java | 3 +- .../azrael/size/SizeReflectionHandler.java | 2 +- 9 files changed, 195 insertions(+), 34 deletions(-) create mode 100644 Source/Size/src/ca/uqac/lif/azrael/size/NullPrintHandler.java create mode 100644 Source/Size/src/ca/uqac/lif/azrael/size/RotePrintHandler.java diff --git a/Source/Core/src/ca/uqac/lif/azrael/ObjectPrinter.java b/Source/Core/src/ca/uqac/lif/azrael/ObjectPrinter.java index 34556b6..d458d05 100644 --- a/Source/Core/src/ca/uqac/lif/azrael/ObjectPrinter.java +++ b/Source/Core/src/ca/uqac/lif/azrael/ObjectPrinter.java @@ -129,4 +129,24 @@ public static String getVersionString() { return "2.0"; } + + /** + * Adds a handler to the printer + * @param h The handler + */ + public void addHandler(PrintHandler h) + { + m_handlers.add(h); + } + + /** + * Sets whether the printer uses the {@link Printable} interface when an + * object provides one. + * @param b Set to true to use the interface, false to + * override it + */ + public void setUsePrintable(boolean b) + { + m_usePrintable = b; + } } diff --git a/Source/Core/src/ca/uqac/lif/azrael/ObjectReader.java b/Source/Core/src/ca/uqac/lif/azrael/ObjectReader.java index 480d633..cb734a6 100644 --- a/Source/Core/src/ca/uqac/lif/azrael/ObjectReader.java +++ b/Source/Core/src/ca/uqac/lif/azrael/ObjectReader.java @@ -39,18 +39,18 @@ public abstract class ObjectReader * Additional class loaders */ protected Set m_classLoaders; - + /** * A list of objects that handle the printing of objects of various * types */ protected List> m_handlers; - + /** * The default handler to use when no other accepts an object */ protected ReadHandler m_reflectionHandler = new ReflectionReadHandler(this); - + /** * Creates a new object reader */ @@ -154,7 +154,7 @@ public Object getInstance(Class clazz) throws ReadException } return o; } - + /** * Adds a new class loader used to create new class instances * @param cl The class loader @@ -214,27 +214,36 @@ public Class findClass(String class_name) throws ClassNotFoundException */ public static void setField(Object o, String field_name, Object value) throws ReadException { - if (o == null) - { - return; - } - try - { - Field fld = ReflectionPrintHandler.getFromAllFields(field_name, o.getClass()); - fld.setAccessible(true); - fld.set(o, value); - } - catch (NoSuchFieldException e) - { - throw new ReadException(e); - } - catch (IllegalArgumentException e) - { - throw new ReadException(e); - } - catch (IllegalAccessException e) - { - throw new ReadException(e); - } + if (o == null) + { + return; + } + try + { + Field fld = ReflectionPrintHandler.getFromAllFields(field_name, o.getClass()); + fld.setAccessible(true); + fld.set(o, value); + } + catch (NoSuchFieldException e) + { + throw new ReadException(e); + } + catch (IllegalArgumentException e) + { + throw new ReadException(e); + } + catch (IllegalAccessException e) + { + throw new ReadException(e); + } + } + + /** + * Adds a handler to the reader + * @param h The handler + */ + public void addHandler(ReadHandler h) + { + m_handlers.add(h); } } diff --git a/Source/Core/src/ca/uqac/lif/azrael/ReflectionPrintHandler.java b/Source/Core/src/ca/uqac/lif/azrael/ReflectionPrintHandler.java index 3ed455c..af2cd4c 100644 --- a/Source/Core/src/ca/uqac/lif/azrael/ReflectionPrintHandler.java +++ b/Source/Core/src/ca/uqac/lif/azrael/ReflectionPrintHandler.java @@ -39,12 +39,12 @@ public class ReflectionPrintHandler implements PrintHandler * The internal object printer */ protected ObjectPrinter m_printer; - + /** * Whether the fields marked as transient should be ignored */ protected boolean m_ignoreTransient = true; - + /** * Creates a new reflection print handler * @param p The internal object printer @@ -88,12 +88,12 @@ public T handle(Object o) throws PrintException } return encapsulateFields(o, contents); } - + protected T encapsulateFields(Object o, Map contents) throws PrintException { return m_printer.wrap(o, m_printer.print(contents)); } - + protected static List getAllFields(List fields, Class type) { fields.addAll(Arrays.asList(type.getDeclaredFields())); diff --git a/Source/Core/src/ca/uqac/lif/azrael/fridge/SerializeFridge.java b/Source/Core/src/ca/uqac/lif/azrael/fridge/SerializeFridge.java index 3e3730a..b05a065 100644 --- a/Source/Core/src/ca/uqac/lif/azrael/fridge/SerializeFridge.java +++ b/Source/Core/src/ca/uqac/lif/azrael/fridge/SerializeFridge.java @@ -52,6 +52,7 @@ public void store(Object o) throws FridgeException { throw new FridgeException(e); } + m_printer.reset(); } @Override diff --git a/Source/Size/src/ca/uqac/lif/azrael/size/CollectionPrintHandler.java b/Source/Size/src/ca/uqac/lif/azrael/size/CollectionPrintHandler.java index 046d83c..fc5e703 100644 --- a/Source/Size/src/ca/uqac/lif/azrael/size/CollectionPrintHandler.java +++ b/Source/Size/src/ca/uqac/lif/azrael/size/CollectionPrintHandler.java @@ -87,7 +87,7 @@ public Number getSize(Object o) throws PrintException } return size; } - if (o instanceof ArrayList || o instanceof ArrayDeque) + if (o instanceof ArrayList) { ArrayList col = (ArrayList) o; int size = 48 + 4 * col.size(); @@ -97,7 +97,16 @@ public Number getSize(Object o) throws PrintException } return size; } + if (o instanceof ArrayDeque) + { + ArrayDeque col = (ArrayDeque) o; + int size = 48 + 4 * col.size(); + for (Object elem : col) + { + size += (Integer) m_printer.print(elem); + } + return size; + } return 0; } - } diff --git a/Source/Size/src/ca/uqac/lif/azrael/size/NullPrintHandler.java b/Source/Size/src/ca/uqac/lif/azrael/size/NullPrintHandler.java new file mode 100644 index 0000000..a889cf2 --- /dev/null +++ b/Source/Size/src/ca/uqac/lif/azrael/size/NullPrintHandler.java @@ -0,0 +1,41 @@ +/* + Azrael, a serializer for Java objects + Copyright (C) 2016-2019 Sylvain Hallé + Laboratoire d'informatique formelle + Université du Québec à Chicoutimi, Canada + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + */ +package ca.uqac.lif.azrael.size; + +import ca.uqac.lif.azrael.PrintException; + +public class NullPrintHandler extends ReferencePrintHandler +{ + public NullPrintHandler(SizePrinter printer) + { + super(printer); + } + + @Override + public boolean canHandle(Object o) + { + return o == null; + } + + @Override + public Number getSize(Object o) throws PrintException + { + return 0; + } +} diff --git a/Source/Size/src/ca/uqac/lif/azrael/size/RotePrintHandler.java b/Source/Size/src/ca/uqac/lif/azrael/size/RotePrintHandler.java new file mode 100644 index 0000000..5ce7b7a --- /dev/null +++ b/Source/Size/src/ca/uqac/lif/azrael/size/RotePrintHandler.java @@ -0,0 +1,80 @@ +/* + Azrael, a serializer for Java objects + Copyright (C) 2016-2019 Sylvain Hallé + Laboratoire d'informatique formelle + Université du Québec à Chicoutimi, Canada + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + */ +package ca.uqac.lif.azrael.size; + +import java.util.IdentityHashMap; + +import ca.uqac.lif.azrael.PrintHandler; + +/** + * Print handler that returns a fixed size value for all objects matching + * a given class name. Adding such a handler to a size printer can be useful + * to cut off the recursive decomposition of "strange" objects. + * + * @author Sylvain Hallé + */ +public class RotePrintHandler implements PrintHandler +{ + /** + * A map of already seen objects + */ + protected IdentityHashMap m_seenObjects; + + /** + * The name of the class to match + */ + protected String m_className; + + /** + * The size to return for this object + */ + protected int m_sizeToReturn; + + public RotePrintHandler(String class_name, int size) + { + super(); + m_className = class_name; + m_sizeToReturn = size; + m_seenObjects = new IdentityHashMap(); + } + + @Override + public boolean canHandle(Object o) + { + return o != null && o.getClass().getSimpleName().compareTo(m_className) == 0; + } + + @Override + public Number handle(Object o) + { + // We count objects only once + if (m_seenObjects.containsKey(o)) + { + return 0; + } + m_seenObjects.put(o, 1); + return m_sizeToReturn; + } + + @Override + public void reset() + { + m_seenObjects.clear(); + } +} \ No newline at end of file diff --git a/Source/Size/src/ca/uqac/lif/azrael/size/SizePrinter.java b/Source/Size/src/ca/uqac/lif/azrael/size/SizePrinter.java index a681e02..5d9c959 100644 --- a/Source/Size/src/ca/uqac/lif/azrael/size/SizePrinter.java +++ b/Source/Size/src/ca/uqac/lif/azrael/size/SizePrinter.java @@ -23,7 +23,7 @@ public class SizePrinter extends ObjectPrinter { - public static final int OBJECT_SHELL_SIZE = 8; + public static final int OBJECT_SHELL_SIZE = 24; public static final int OBJREF_SIZE = 4; public static final int LONG_FIELD_SIZE = 8; public static final int INT_FIELD_SIZE = 4; @@ -37,6 +37,7 @@ public class SizePrinter extends ObjectPrinter public SizePrinter() { super(); + m_handlers.add(new NullPrintHandler(this)); m_handlers.add(new NumberPrintHandler()); m_handlers.add(new StringPrintHandler(this)); m_handlers.add(new BooleanPrintHandler()); diff --git a/Source/Size/src/ca/uqac/lif/azrael/size/SizeReflectionHandler.java b/Source/Size/src/ca/uqac/lif/azrael/size/SizeReflectionHandler.java index f306756..f2c2c28 100644 --- a/Source/Size/src/ca/uqac/lif/azrael/size/SizeReflectionHandler.java +++ b/Source/Size/src/ca/uqac/lif/azrael/size/SizeReflectionHandler.java @@ -46,7 +46,7 @@ public Number handle(Object o) throws PrintException return 0; } m_seenObjects.put(o, 1); - int size = 24; // Basic overhead of a Java object + int size = SizePrinter.OBJECT_SHELL_SIZE; // Basic overhead of a Java object for (Field field : getAllFields(o.getClass())) { // Is this field declared as transient?