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

com.github.davidmoten.rx.Serialized Maven / Gradle / Ivy

package com.github.davidmoten.rx;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

import rx.Observable;
import rx.Observer;
import rx.functions.Action1;
import rx.functions.Func0;
import rx.functions.Func1;
import rx.observables.SyncOnSubscribe;

/**
 * Utility class for writing Observable streams to ObjectOutputStreams and
 * reading Observable streams of indeterminate size from ObjectInputStreams.
 */
public final class Serialized {

    private static final int DEFAULT_BUFFER_SIZE = 8192;

    /**
     * Returns the deserialized objects from the given {@link InputStream} as an
     * {@link Observable} stream.
     * 
     * @param ois
     *            the {@link ObjectInputStream}
     * @param 
     *            the generic type of the returned stream
     * @return the stream of deserialized objects from the {@link InputStream}
     *         as an {@link Observable}.
     */
    public static  Observable read(final ObjectInputStream ois) {
        return Observable.create(new SyncOnSubscribe() {

            @Override
            protected ObjectInputStream generateState() {
               return ois;
            }

            @Override
            protected ObjectInputStream next(ObjectInputStream ois, Observer observer) {
                try {
                    @SuppressWarnings("unchecked")
                    T t = (T) ois.readObject();
                    observer.onNext(t);
                } catch (EOFException e) {
                    observer.onCompleted();
                } catch (ClassNotFoundException e) {
                    observer.onError(e);
                } catch (IOException e) {
                    observer.onError(e);
                }
                return ois;
            }
        });
    }

    /**
     * Returns the deserialized objects from the given {@link File} as an
     * {@link Observable} stream. Uses buffer of size bufferSize
     * buffer reads from the File.
     * 
     * @param file
     *            the input file
     * @param bufferSize
     *            the buffer size for reading bytes from the file.
     * @param 
     *            the generic type of the deserialized objects returned in the
     *            stream
     * @return the stream of deserialized objects from the {@link InputStream}
     *         as an {@link Observable}.
     */
    public static  Observable read(final File file,
            final int bufferSize) {
        Func0 resourceFactory = new Func0() {
            @Override
            public ObjectInputStream call() {
                try {
                    return new ObjectInputStream(
                            new BufferedInputStream(new FileInputStream(file), bufferSize));
                } catch (FileNotFoundException e) {
                    throw new RuntimeException(e);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        };
        Func1> observableFactory = new Func1>() {

            @Override
            public Observable call(ObjectInputStream is) {
                return read(is);
            }
        };
        Action1 disposeAction = new Action1() {

            @Override
            public void call(ObjectInputStream ois) {
                try {
                    ois.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        };
        return Observable.using(resourceFactory, observableFactory, disposeAction, true);
    }

    /**
     * Returns the deserialized objects from the given {@link File} as an
     * {@link Observable} stream. A buffer size of 8192 bytes is used by
     * default.
     * 
     * @param file
     *            the input file containing serialized java objects
     * @param 
     *            the generic type of the deserialized objects returned in the
     *            stream
     * @return the stream of deserialized objects from the {@link InputStream}
     *         as an {@link Observable}.
     */
    public static  Observable read(final File file) {
        return read(file, DEFAULT_BUFFER_SIZE);
    }

    /**
     * Returns a duplicate of the input stream but with the side effect that
     * emissions from the source are written to the {@link ObjectOutputStream}.
     * 
     * @param source
     *            the source of objects to write
     * @param oos
     *            the output stream to write to
     * @param 
     *            the generic type of the objects being serialized
     * @return re-emits the input stream
     */
    public static  Observable write(Observable source,
            final ObjectOutputStream oos) {
        return source.doOnNext(new Action1() {

            @Override
            public void call(T t) {
                try {
                    oos.writeObject(t);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }

    /**
     * Writes the source stream to the given file in given append mode and using
     * the given buffer size.
     * 
     * @param source
     *            observable stream to write
     * @param file
     *            file to write to
     * @param append
     *            if true writes are appended to file otherwise overwrite the
     *            file
     * @param bufferSize
     *            the buffer size in bytes to use.
     * @param 
     *            the generic type of the input stream
     * @return re-emits the input stream
     */
    public static  Observable write(final Observable source,
            final File file, final boolean append, final int bufferSize) {
        Func0 resourceFactory = new Func0() {
            @Override
            public ObjectOutputStream call() {
                try {
                    return new ObjectOutputStream(new BufferedOutputStream(
                            new FileOutputStream(file, append), bufferSize));
                } catch (FileNotFoundException e) {
                    throw new RuntimeException(e);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        };
        Func1> observableFactory = new Func1>() {

            @Override
            public Observable call(ObjectOutputStream oos) {
                return write(source, oos);
            }
        };
        Action1 disposeAction = new Action1() {

            @Override
            public void call(ObjectOutputStream oos) {
                try {
                    oos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        };
        return Observable.using(resourceFactory, observableFactory, disposeAction, true);
    }

    /**
     * Writes the source stream to the given file in given append mode and using
     * the a buffer size of 8192 bytes.
     * 
     * @param source
     *            observable stream to write
     * @param file
     *            file to write to
     * @param append
     *            if true writes are appended to file otherwise overwrite the
     *            file
     * @param 
     *            the generic type of the input stream
     * @return re-emits the input stream
     */
    public static  Observable write(final Observable source,
            final File file, final boolean append) {
        return write(source, file, append, DEFAULT_BUFFER_SIZE);
    }

    /**
     * Writes the source stream to the given file in given append mode and using
     * the a buffer size of 8192 bytes.
     * 
     * @param source
     *            observable stream to write
     * @param file
     *            file to write to
     * @param 
     *            the generic type of the input stream
     * @return re-emits the input stream
     */
    public static  Observable write(final Observable source,
            final File file) {
        return write(source, file, false, DEFAULT_BUFFER_SIZE);
    }

    public static KryoBuilder kryo() {
        return kryo(new Kryo());
    }

    public static KryoBuilder kryo(Kryo kryo) {
        return new KryoBuilder(kryo);
    }

    public static class KryoBuilder {

        private static final int DEFAULT_BUFFER_SIZE = 4096;

        private final Kryo kryo;

        private KryoBuilder(Kryo kryo) {
            this.kryo = kryo;
        }

        public  Observable write(final Observable source, final File file) {
            return write(source, file, false, DEFAULT_BUFFER_SIZE);
        }

        public  Observable write(final Observable source, final File file,
                boolean append) {
            return write(source, file, append, DEFAULT_BUFFER_SIZE);
        }

        public  Observable write(final Observable source, final File file,
                final boolean append, final int bufferSize) {
            Func0 resourceFactory = new Func0() {
                @Override
                public Output call() {
                    try {
                        return new Output(new FileOutputStream(file, append), bufferSize);
                    } catch (FileNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                }
            };
            Func1> observableFactory = new Func1>() {

                @Override
                public Observable call(final Output output) {
                    return source.doOnNext(new Action1() {
                        @Override
                        public void call(T t) {
                            kryo.writeObject(output, t);
                        }
                    });
                }
            };
            Action1 disposeAction = new Action1() {

                @Override
                public void call(Output output) {
                    output.close();
                }
            };
            return Observable.using(resourceFactory, observableFactory, disposeAction, true);
        }

        public  Observable read(Class cls, final File file) {
            return read(cls, file, DEFAULT_BUFFER_SIZE);
        }

        public  Observable read(final Class cls, final File file, final int bufferSize) {
            Func0 resourceFactory = new Func0() {
                @Override
                public Input call() {
                    try {
                        return new Input(new FileInputStream(file), bufferSize);
                    } catch (FileNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                }
            };
            Func1> observableFactory = new Func1>() {

                @Override
                public Observable call(final Input input) {
                    return read(cls, input, bufferSize);
                }
            };
            Action1 disposeAction = new Action1() {

                @Override
                public void call(Input input) {
                    input.close();
                }
            };
            return Observable.using(resourceFactory, observableFactory, disposeAction, true);
        }

        public  Observable read(final Class cls, final Input input, final int bufferSize) {

            return Observable.create(new SyncOnSubscribe() {

                @Override
                protected Input generateState() {
                    return input;
                }

                @Override
                protected Input next(Input arg0, Observer observer) {
                    if (input.eof()) {
                        observer.onCompleted();
                    } else {
                        T t = kryo.readObject(input, cls);
                        observer.onNext(t);
                    }
                    return input;
                }
            });
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy