001    /*
002     * $Id: AbstractSerializer.java,v 1.4 2014/01/04 21:56:42 oboehm Exp $
003     *
004     * Copyright (c) 2013 by Oliver Boehm
005     *
006     * Licensed under the Apache License, Version 2.0 (the "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *   http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     *
018     * (c)reated 30.11.2013 by oliver (ob@oasd.de)
019     */
020    
021    package patterntesting.runtime.io;
022    
023    import java.io.*;
024    import java.net.URI;
025    
026    import org.slf4j.*;
027    
028    import patterntesting.runtime.monitor.ClasspathMonitor;
029    
030    /**
031     * This is the common superclass for all Serializer casses in PatternTesting.
032     * This class was introduced to be able to abstract from the used XStream
033     * library in the log package. This allows us to declare the xstream library
034     * as "optional" in the POM file.
035     *
036     * @author oliver
037     * @since 1.4 (30.11.2013)
038     */
039    public abstract class AbstractSerializer {
040    
041        private static final Logger log = LoggerFactory.getLogger(AbstractSerializer.class);
042        private static final AbstractSerializer instance;
043    
044        static {
045            if (isXStreamAvailable()) {
046                instance = new XStreamSerializer();
047            } else {
048                instance = new BinarySerializer();
049            }
050        }
051    
052        private static boolean isXStreamAvailable() {
053            String xstreamClassname ="com.thoughtworks.xstream.XStream";
054            URI xstreamURI = ClasspathMonitor.getInstance().whichClass(xstreamClassname);
055            if (xstreamURI == null) {
056                log.debug("{} not found in classpath for serialization.", xstreamClassname);
057                return false;
058            } else {
059                log.debug("{} found in {} for serialization.", xstreamClassname, xstreamURI);
060                return true;
061            }
062        }
063    
064        /**
065         * This static method returns an instance of the default serializer.
066         * Normally this is the {@link XStreamSerializer} if the xstream library is
067         * detected in the classpath. If not the {@link BinarySerializer} (which
068         * requires the serialized objects to be {@link Serializable}) will be used
069         * as fallback.
070         *
071         * @return the default serializer
072         */
073        public static AbstractSerializer getInstance() {
074            return instance;
075        }
076    
077        /**
078         * Creates the {@link ObjectInputStream} that deserializes a stream of
079         * objects from an InputStream.
080         *
081         * @param in the input stream
082         * @return the object input stream
083         * @throws IOException Signals that an I/O exception has occurred.
084         */
085        public abstract ObjectInputStream createObjectInputStream(InputStream in)
086                throws IOException;
087    
088        /**
089         * Creates the {@link ObjectOutputStream} that serializees a stream of
090         * objects to the {@link OutputStream}.
091         *
092         * @param out the output stream
093         * @return the object output stream
094         * @throws IOException Signals that an I/O exception has occurred.
095         */
096        public abstract ObjectOutputStream createObjectOutputStream(OutputStream out)
097                throws IOException;
098    
099        /**
100         * Loads a single ojbect from the given file.
101         *
102         * @param file the file
103         * @return the object
104         * @throws IOException Signals that an I/O exception has occurred.
105         * @throws ClassNotFoundException the class not found exception
106         */
107        public Object load(final File file) throws IOException, ClassNotFoundException {
108            InputStream istream = new FileInputStream(file);
109            try {
110                return load(istream);
111            } finally {
112                istream.close();
113            }
114        }
115    
116        /**
117         * Loads a single ojbect from the given stream.
118         *
119         * @param in the in
120         * @return the object
121         * @throws IOException Signals that an I/O exception has occurred.
122         * @throws ClassNotFoundException the class not found exception
123         */
124        public Object load(final InputStream in) throws IOException, ClassNotFoundException {
125            ObjectInputStream objStream = this.createObjectInputStream(in);
126            return objStream.readObject();
127        }
128    
129        /**
130         * Saves a single object to the given file.
131         *
132         * @param object the object
133         * @param file the file
134         * @throws IOException Signals that an I/O exception has occurred.
135         */
136        public void save(final Object object, final File file) throws IOException {
137            OutputStream ostream = new FileOutputStream(file);
138            try {
139                save(object, ostream);
140                ostream.flush();
141            } finally {
142                ostream.close();
143            }
144        }
145    
146        /**
147         * Saves a single object to the given stream.
148         *
149         * @param object the object
150         * @param out the out
151         * @throws IOException Signals that an I/O exception has occurred.
152         */
153        public void save(final Object object, final OutputStream out) throws IOException {
154           ObjectOutputStream objStream = this.createObjectOutputStream(out);
155           objStream.writeObject(object);
156           objStream.flush();
157        }
158    
159    }
160