001    /*
002     * $Id: AbstractLogger.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 07.09.2013 by oliver (ob@oasd.de)
019     */
020    
021    package patterntesting.runtime.log;
022    
023    import java.io.*;
024    
025    import org.apache.commons.io.IOUtils;
026    import org.slf4j.*;
027    
028    import patterntesting.runtime.io.BetterFileOutputStream;
029    
030    /**
031     * This is a common super class for all classes which do a kind of logging.
032     * It provides an {@link OutputStream} and guarantees that this stream is
033     * closed at least at shutdown.
034     *
035     * @author oliver
036     * @since 1.3.1 (07.09.2013)
037     */
038    public abstract class AbstractLogger extends Thread {
039    
040        private static Logger log = LoggerFactory.getLogger(AbstractLogger.class);
041        private final OutputStream logStream;
042    
043        /**
044         * Instantiates a new abstract logger.
045         *
046         * @param ostream the ostream
047         */
048        protected AbstractLogger(final OutputStream ostream) {
049            this.logStream = ostream;
050            Runtime.getRuntime().addShutdownHook(this);
051            log.debug("{} is registered as shutdown hook for closing {}.", this, this.logStream);
052        }
053    
054        /**
055         * Creates a file in the temp directory. If this was not successful a file
056         * <code>prefix + suffix</code> is returned as result.
057         *
058         * @param prefix the prefix
059         * @param suffix the suffix
060         * @return the file
061         */
062        protected static File createTempLogFile(final String prefix, final String suffix) {
063            try {
064                return File.createTempFile(prefix, suffix);
065            } catch (IOException ioe) {
066                log.info("Cannot create temporary log file.", ioe);
067                return new File(prefix + suffix);
068            }
069        }
070    
071        /**
072         * Gets the stream for the given log file. As fallback <em>stdout</em>
073         * will be used.
074         *
075         * @param logFile the log file
076         * @return the stream for
077         */
078        protected static OutputStream getStreamFor(final File logFile) {
079            if (logFile.exists()) {
080                if (logFile.delete()) {
081                    log.info("Old log file \"{}\" was deleted.", logFile);
082                } else {
083                    log.warn("Old log file \"{}\" could not be deleted!", logFile);
084                }
085            }
086            try {
087                return new BetterFileOutputStream(logFile, true);
088            } catch (FileNotFoundException fnfe) {
089                log.info("Will log to stdout because cannot log to \"{}\" ({}).", logFile,
090                        fnfe.getMessage());
091                return System.out;
092            }
093        }
094    
095        /**
096         * Gets the log stream.
097         *
098         * @return the logStream
099         */
100        protected final OutputStream getLogStream() {
101            return logStream;
102        }
103    
104        /**
105         * This method is called at shutdown to close the open stream.
106         * Otherwise the closing "</object-stream>" tag in the generated file
107         * would be missing (it is generated by the used XStream library).
108         *
109         * @see java.lang.Thread#run()
110         */
111        @Override
112        public void run() {
113            IOUtils.closeQuietly(this.logStream);
114            log.debug("{} is closed.", this.logStream);
115        }
116    
117        /**
118         * Closes the stream with the logged objects.
119         */
120        public void close() {
121            IOUtils.closeQuietly(this.logStream);
122            Runtime.getRuntime().removeShutdownHook(this);
123            log.debug("{} is closed and {} removed as shutdown hook.", this.logStream, this);
124        }
125    
126        /**
127         * To string.
128         *
129         * @return the string
130         * @see java.lang.Object#toString()
131         */
132        @Override
133        public String toString() {
134            return this.getClass().getSimpleName() + "@" + Integer.toString(this.hashCode(), Character.MAX_RADIX);
135        }
136    
137    }
138