X-Git-Url: http://git.nikiroo.be/?p=nikiroo-utils.git;a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2Fserial%2FSerialUtils.java;h=3770c588ce53bc25e77b623ee715da6aa58b937e;hp=657dbec45fb069e26b77cc7423c0c606ffdc6a39;hb=aad145868879e293dbe391c005c1a6885341529b;hpb=db31c35860081535d6e7ddc83ab4af573bb0522e diff --git a/src/be/nikiroo/utils/serial/SerialUtils.java b/src/be/nikiroo/utils/serial/SerialUtils.java index 657dbec..3770c58 100644 --- a/src/be/nikiroo/utils/serial/SerialUtils.java +++ b/src/be/nikiroo/utils/serial/SerialUtils.java @@ -1,5 +1,8 @@ package be.nikiroo.utils.serial; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.io.NotSerializableException; import java.lang.reflect.Field; import java.util.HashMap; @@ -13,13 +16,64 @@ import java.util.Map; * * @author niki */ -class SerialUtils { +public class SerialUtils { private static Map customTypes; static { customTypes = new HashMap(); // TODO: add "default" custom serialisers } + + /** + * Create an empty object of the given type. + * + * @param type + * the object type (its class name) + * + * @return the new object + * + * @throws NoSuchMethodException if the given class is not compatible with this code + * @throws ClassNotFoundException if the class cannot be found or created + */ + public static Object createObject(String type) throws NoSuchMethodException, + ClassNotFoundException { + + try { + Class clazz = getClass(type); + if (clazz == null) { + throw new ClassNotFoundException("Class not found: " + type); + } + + String className = clazz.getName(); + Object[] args = null; + Constructor ctor = null; + if (className.contains("$")) { + Object javaParent = createObject(className.substring(0, + className.lastIndexOf('$'))); + args = new Object[] { javaParent }; + ctor = clazz.getDeclaredConstructor(new Class[] { javaParent + .getClass() }); + } else { + args = new Object[] {}; + ctor = clazz.getDeclaredConstructor(); + } + + ctor.setAccessible(true); + return ctor.newInstance(args); + } catch (NoSuchMethodException e) { + throw new NoSuchMethodException( + String.format( + "Objects of type \"%s\" cannot be created by this code: maybe the class" + + " or its enclosing class doesn't have an empty constructor?", + type)); + + } + catch (SecurityException e) { throw new ClassNotFoundException("Cannot instantiate: " + type, e); } + catch (InstantiationException e) { throw new ClassNotFoundException("Cannot instantiate: " + type, e); } + catch (IllegalAccessException e) { throw new ClassNotFoundException("Cannot instantiate: " + type, e); } + catch (IllegalArgumentException e) { throw new ClassNotFoundException("Cannot instantiate: " + type, e); } + catch (InvocationTargetException e) { throw new ClassNotFoundException("Cannot instantiate: " + type, e); } + } static public void addCustomSerializer(CustomSerializer serializer) { customTypes.put(serializer.getType(), serializer); @@ -152,7 +206,38 @@ class SerialUtils { return Integer.parseInt(encodedValue); } } + + static private Class getClass(String type) throws ClassNotFoundException, + NoSuchMethodException { + Class clazz = null; + try { + clazz = Class.forName(type); + } catch (ClassNotFoundException e) { + int pos = type.length(); + pos = type.lastIndexOf(".", pos); + if (pos >= 0) { + String parentType = type.substring(0, pos); + String nestedType = type.substring(pos + 1); + Class javaParent = null; + try { + javaParent = getClass(parentType); + parentType = javaParent.getName(); + clazz = Class.forName(parentType + "$" + nestedType); + } catch (Exception ee) { + } + if (javaParent == null) { + throw new NoSuchMethodException( + "Class not found: " + + type + + " (the enclosing class cannot be created: maybe it doesn't have an empty constructor?)"); + } + } + } + + return clazz; + } + // aa bb -> "aa\tbb" private static void encodeString(StringBuilder builder, String raw) { builder.append('\"');