X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2Fserial%2FImporter.java;h=81814dfdbadf6a71ec2224d14be5926314bbd105;hb=3519cb5c518d569235beaedfc3071cba45ec848d;hp=bca157c501bcb8a512fd5367585b15a06a82771e;hpb=a43e4f72629d04cd3122bde830b6e4925fd3aa91;p=fanfix.git diff --git a/src/be/nikiroo/utils/serial/Importer.java b/src/be/nikiroo/utils/serial/Importer.java deleted file mode 100644 index bca157c..0000000 --- a/src/be/nikiroo/utils/serial/Importer.java +++ /dev/null @@ -1,297 +0,0 @@ -package be.nikiroo.utils.serial; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; - -import be.nikiroo.utils.StringUtils; - -/** - * A simple class that can accept the output of {@link Exporter} to recreate - * objects as they were sent to said exporter. - *

- * This class requires the objects (and their potential enclosing objects) to - * have an empty constructor, and does not support inner classes (it does - * support nested classes, though). - * - * @author niki - */ -public class Importer { - static private Integer SIZE_ID = null; - static private byte[] NEWLINE = null; - - private Boolean link; - private Object me; - private Importer child; - private Map map; - - private String currentFieldName; - - static { - try { - SIZE_ID = "EXT:".getBytes("UTF-8").length; - NEWLINE = "\n".getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - // UTF-8 is mandated to exist on confirming jre's - } - } - - /** - * Create a new {@link Importer}. - */ - public Importer() { - map = new HashMap(); - map.put("NULL", null); - } - - private Importer(Map map) { - this.map = map; - } - - /** - * Read some data into this {@link Importer}: it can be the full serialised - * content, or a number of lines of it (any given line MUST be - * complete though) and accumulate it with the already present data. - * - * @param data - * the data to parse - * - * @return itself so it can be chained - * - * @throws NoSuchFieldException - * if the serialised data contains information about a field - * which does actually not exist in the class we know of - * @throws NoSuchMethodException - * if a class described in the serialised data cannot be created - * because it is not compatible with this code - * @throws ClassNotFoundException - * if a class described in the serialised data cannot be found - * @throws IOException - * if the content cannot be read (for instance, corrupt data) - */ - public Importer read(String data) throws NoSuchFieldException, - NoSuchMethodException, ClassNotFoundException, IOException { - return read(data.getBytes("UTF-8"), 0); - } - - /** - * Read some data into this {@link Importer}: it can be the full serialised - * content, or a number of lines of it (any given line MUST be - * complete though) and accumulate it with the already present data. - * - * @param data - * the data to parse - * @param offset - * the offset at which to start reading the data (we ignore - * anything that goes before that offset) - * - * @return itself so it can be chained - * - * @throws NoSuchFieldException - * if the serialised data contains information about a field - * which does actually not exist in the class we know of - * @throws NoSuchMethodException - * if a class described in the serialised data cannot be created - * because it is not compatible with this code - * @throws ClassNotFoundException - * if a class described in the serialised data cannot be found - * @throws IOException - * if the content cannot be read (for instance, corrupt data) - */ - private Importer read(byte[] data, int offset) throws NoSuchFieldException, - NoSuchMethodException, ClassNotFoundException, IOException { - - int dataStart = offset; - while (dataStart < data.length) { - String id = ""; - if (data.length - dataStart >= SIZE_ID) { - id = new String(data, dataStart, SIZE_ID); - } - - boolean zip = id.equals("ZIP:"); - boolean b64 = id.equals("B64:"); - if (zip || b64) { - dataStart += SIZE_ID; - } - - int count = find(data, dataStart, NEWLINE); - count -= dataStart; - if (count < 0) { - count = data.length - dataStart; - } - - if (zip || b64) { - boolean unpacked = false; - try { - byte[] line = StringUtils.unbase64(data, dataStart, count, - zip); - unpacked = true; - read(line, 0); - } catch (IOException e) { - throw new IOException("Internal error when decoding " - + (unpacked ? "unpacked " : "") - + (zip ? "ZIP" : "B64") - + " content: input may be corrupt"); - } - } else { - String line = new String(data, dataStart, count, "UTF-8"); - processLine(line); - } - - dataStart += count + NEWLINE.length; - } - - return this; - } - - /** - * Read a single (whole) line of serialised data into this {@link Importer} - * and accumulate it with the already present data. - * - * @param line - * the line to parse - * - * @return TRUE if we are just done with one object or sub-object - * - * @throws NoSuchFieldException - * if the serialised data contains information about a field - * which does actually not exist in the class we know of - * @throws NoSuchMethodException - * if a class described in the serialised data cannot be created - * because it is not compatible with this code - * @throws ClassNotFoundException - * if a class described in the serialised data cannot be found - * @throws IOException - * if the content cannot be read (for instance, corrupt data) - */ - private boolean processLine(String line) throws NoSuchFieldException, - NoSuchMethodException, ClassNotFoundException, IOException { - // Defer to latest child if any - if (child != null) { - if (child.processLine(line)) { - if (currentFieldName != null) { - setField(currentFieldName, child.getValue()); - currentFieldName = null; - } - child = null; - } - - return false; - } - - if (line.equals("{")) { // START: new child if needed - if (link != null) { - child = new Importer(map); - } - } else if (line.equals("}")) { // STOP: report self to parent - return true; - } else if (line.startsWith("REF ")) { // REF: create/link self - String[] tab = line.substring("REF ".length()).split("@"); - String type = tab[0]; - tab = tab[1].split(":"); - String ref = tab[0]; - - link = map.containsKey(ref); - if (link) { - me = map.get(ref); - } else { - if (line.endsWith(":")) { - // construct - me = SerialUtils.createObject(type); - } else { - // direct value - int pos = line.indexOf(":"); - String encodedValue = line.substring(pos + 1); - me = SerialUtils.decode(encodedValue); - } - map.put(ref, me); - } - } else { // FIELD: new field *or* direct simple value - if (line.endsWith(":")) { - // field value is compound - currentFieldName = line.substring(0, line.length() - 1); - } else if (line.startsWith(":") || !line.contains(":") - || line.startsWith("\"") || CustomSerializer.isCustom(line)) { - // not a field value but a direct value - me = SerialUtils.decode(line); - } else { - // field value is direct - int pos = line.indexOf(":"); - String fieldName = line.substring(0, pos); - String encodedValue = line.substring(pos + 1); - Object value = null; - value = SerialUtils.decode(encodedValue); - - // To support simple types directly: - if (me == null) { - me = value; - } else { - setField(fieldName, value); - } - } - } - - return false; - } - - private void setField(String name, Object value) - throws NoSuchFieldException { - - try { - Field field = me.getClass().getDeclaredField(name); - - field.setAccessible(true); - field.set(me, value); - } catch (NoSuchFieldException e) { - throw new NoSuchFieldException(String.format( - "Field \"%s\" was not found in object of type \"%s\".", - name, me.getClass().getCanonicalName())); - } catch (Exception e) { - throw new NoSuchFieldException(String.format( - "Internal error when setting \"%s.%s\": %s", me.getClass() - .getCanonicalName(), name, e.getMessage())); - } - } - - /** - * Find the given needle in the data and return its position (or -1 if not - * found). - * - * @param data - * the data to look through - * @param offset - * the offset at wich to start searching - * @param needle - * the needle to find - * - * @return the position of the needle if found, -1 if not found - */ - private int find(byte[] data, int offset, byte[] needle) { - for (int i = offset; i + needle.length - 1 < data.length; i++) { - boolean same = true; - for (int j = 0; j < needle.length; j++) { - if (data[i + j] != needle[j]) { - same = false; - break; - } - } - - if (same) { - return i; - } - } - - return -1; - } - - /** - * Return the current deserialised value. - * - * @return the current value - */ - public Object getValue() { - return me; - } -} \ No newline at end of file