org.red5.io.object.Serializer.java Source code

Java tutorial

Introduction

Here is the source code for org.red5.io.object.Serializer.java

Source

package org.red5.io.object;

/*
 * RED5 Open Source Flash Server - http://www.osflash.org/red5
 *
 * Copyright (c) 2006-2007 by respective authors (see below). All rights reserved.
 *
 * This library 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 2.1 of the License, or (at your option) any later
 * version.
 *
 * This library 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 library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.BeanMap;
import org.red5.io.amf3.ByteArray;
import org.red5.io.amf3.IExternalizable;
import org.red5.io.utils.ObjectMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;

/**
 * The Serializer class writes data output and handles the data according to the
 * core data types
 *
 * @author The Red5 Project (red5@osflash.org)
 * @author Luke Hubbard, Codegent Ltd (luke@codegent.com)
 */
public class Serializer {

    /**
     * Logger
     */
    protected static Logger log = LoggerFactory.getLogger(Serializer.class);

    /**
     * Serializes output to a core data type object
     *
     * @param out          Output writer
     * @param any          Object to serialize
     */
    public void serialize(Output out, Object any) {
        if (log.isDebugEnabled()) {
            log.debug("serialize");
        }
        if (any instanceof IExternalizable) {
            // Make sure all IExternalizable objects are serialized as objects
            out.writeObject(any, this);
            return;
        } else if (any instanceof ByteArray) {
            // Write ByteArray objects directly
            out.writeByteArray((ByteArray) any);
            return;
        }

        if (writeBasic(out, any)) {
            if (log.isDebugEnabled()) {
                log.debug("write basic");
            }
            return;
        }

        if (!writeComplex(out, any)) {
            if (log.isDebugEnabled()) {
                log.debug("Unable to serialize: " + any);
            }
        }
    }

    /**
     * Writes a primitive out as an object
     *
     * @param out              Output writer
     * @param basic            Primitive
     * @return boolean         true if object was successfully serialized, false otherwise
     */
    protected boolean writeBasic(Output out, Object basic) {
        if (basic == null) {
            out.writeNull();
        } else if (basic instanceof Boolean) {
            out.writeBoolean((Boolean) basic);
        } else if (basic instanceof Number) {
            out.writeNumber((Number) basic);
        } else if (basic instanceof String) {
            out.writeString((String) basic);
        } else if (basic instanceof Date) {
            out.writeDate((Date) basic);
        } else {
            return false;
        }
        return true;
    }

    /**
     * Writes a complex type object out
     *
     * @param out        Output writer
     * @param complex    Complex datatype object
     * @return boolean   true if object was successfully serialized, false otherwise
     */
    public boolean writeComplex(Output out, Object complex) {
        if (log.isDebugEnabled()) {
            log.debug("writeComplex");
        }
        if (writeListType(out, complex)) {
            return true;
        } else if (writeArrayType(out, complex)) {
            return true;
        } else if (writeXMLType(out, complex)) {
            return true;
        } else if (writeCustomType(out, complex)) {
            return true;
        } else if (writeObjectType(out, complex)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Writes Lists out as a data type
     *
     * @param out             Output write
     * @param listType        List type
     * @return boolean        true if object was successfully serialized, false otherwise
     */
    protected boolean writeListType(Output out, Object listType) {
        if (log.isDebugEnabled()) {
            log.debug("writeListType");
        }
        if (listType instanceof List) {
            writeList(out, (List<?>) listType);
        } else {
            return false;
        }
        return true;
    }

    /**
     * Writes a List out as an Object
     *
     * @param out             Output writer
     * @param list            List to write as Object
     */
    protected void writeList(Output out, List<?> list) {
        // if its a small list, write it as an array
        if (list.size() < 100) {
            out.writeArray(list, this);
            return;
        }
        // else we should check for lots of null values,
        // if there are over 80% then its probably best to do it as a map
        int size = list.size();
        int nullCount = 0;
        for (int i = 0; i < size; i++) {
            if (list.get(i) == null) {
                nullCount++;
            }
        }
        if (nullCount > (size * 0.8)) {
            out.writeMap(list, this);
        } else {
            out.writeArray(list, this);
        }
    }

    /**
     * Writes array (or collection) out as output Arrays, Collections, etc
     *
     * @param out               Output object
     * @param arrType           Array or collection type
     * @return <code>true</code> if the object has been written, otherwise
     *         <code>false</code>
     */
    @SuppressWarnings("all")
    protected boolean writeArrayType(Output out, Object arrType) {
        if (log.isDebugEnabled()) {
            log.debug("writeArrayType");
        }
        if (arrType instanceof Collection) {
            out.writeArray((Collection<Object>) arrType, this);
        } else if (arrType instanceof Iterator) {
            writeIterator(out, (Iterator<Object>) arrType);
        } else if (arrType.getClass().isArray() && arrType.getClass().getComponentType().isPrimitive()) {
            out.writeArray(arrType, this);
        } else if (arrType instanceof Object[]) {
            out.writeArray((Object[]) arrType, this);
        } else {
            return false;
        }
        return true;
    }

    /**
     * Writes an iterator out to the output
     *
     * @param out          Output writer
     * @param it           Iterator to write
     */
    protected void writeIterator(Output out, Iterator<Object> it) {
        if (log.isDebugEnabled()) {
            log.debug("writeIterator");
        }
        // Create LinkedList of collection we iterate thru and write it out later
        LinkedList<Object> list = new LinkedList<Object>();
        while (it.hasNext()) {
            list.addLast(it.next());
        }
        // Write out collection
        out.writeArray(list, this);
    }

    /**
     * Writes an xml type out to the output
     *
     * @param out          Output writer
     * @param xml          XML
     * @return boolean     <code>true</code> if object was successfully written, <code>false</code> otherwise
     */
    protected boolean writeXMLType(Output out, Object xml) {
        if (log.isDebugEnabled()) {
            log.debug("writeXMLType");
        }
        // If it's a Document write it as Document
        if (xml instanceof Document) {
            writeDocument(out, (Document) xml);
        } else {
            return false;
        }
        return true;
    }

    /**
     * Writes a document to the output
     *
     * @param out           Output writer
     * @param doc           Document to write
     */
    protected void writeDocument(Output out, Document doc) {
        out.writeXML(doc);
    }

    /**
     * Write typed object to the output
     *
     * @param out           Output writer
     * @param obj           Object type to write
     * @return <code>true</code> if the object has been written, otherwise
     *         <code>false</code>
     */
    @SuppressWarnings("all")
    protected boolean writeObjectType(Output out, Object obj) {
        if (obj instanceof ObjectMap || obj instanceof BeanMap) {
            out.writeObject((Map) obj, this);
        } else if (obj instanceof Map) {
            out.writeMap((Map) obj, this);
        } else if (obj instanceof RecordSet) {
            out.writeRecordSet((RecordSet) obj, this);
        } else {
            out.writeObject(obj, this);
        }
        return true;
    }

    // Extension points
    /**
     * Pre processes an object
      * TODO // must be implemented
      *
      * @return              Prerocessed object
      * @param any           Object to preprocess
      */
    public Object preProcessExtension(Object any) {
        // Does nothing right now but will later
        return any;
    }

    /**
     * Writes a custom data to the output
     *
     * @param out       Output writer
     * @param obj       Custom data
     * @return <code>true</code> if the object has been written, otherwise
     *         <code>false</code>
     */
    protected boolean writeCustomType(Output out, Object obj) {
        if (out.isCustom(obj)) {
            // Write custom data
            out.writeCustom(obj);
            return true;
        } else {
            return false;
        }
    }

}