001    /*
002     * Cobertura - http://cobertura.sourceforge.net/
003     *
004     * Copyright (C) 2003 jcoverage ltd.
005     * Copyright (C) 2005 Mark Doliner <thekingant@users.sourceforge.net>
006     *
007     * Cobertura is free software; you can redistribute it and/or modify
008     * it under the terms of the GNU General Public License as published
009     * by the Free Software Foundation; either version 2 of the License,
010     * or (at your option) any later version.
011     *
012     * Cobertura is distributed in the hope that it will be useful, but
013     * WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015     * General Public License for more details.
016     *
017     * You should have received a copy of the GNU General Public License
018     * along with Cobertura; if not, write to the Free Software
019     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
020     * USA
021     */
022    
023    package net.sourceforge.cobertura.coverage;
024    
025    import java.io.File;
026    import java.io.FileInputStream;
027    import java.io.FileNotFoundException;
028    import java.io.FileOutputStream;
029    import java.io.IOException;
030    import java.io.InputStream;
031    import java.io.ObjectInputStream;
032    import java.io.ObjectOutputStream;
033    import java.util.Collections;
034    import java.util.HashMap;
035    import java.util.Iterator;
036    import java.util.Map;
037    import java.util.Set;
038    
039    import org.apache.log4j.Logger;
040    
041    /**
042     * <p>
043     * This class implements HasBeenInstrumented so that when cobertura
044     * instruments itself, it will omit this class.  It does this to
045     * avoid an infinite recursion problem because instrumented classes
046     * make use of this class.
047     * </p>
048     */
049    public class InstrumentationPersistence implements HasBeenInstrumented
050    {
051    
052            /**
053             * Default file name used to write instrumentation information.
054             */
055            public static final String FILE_NAME = "cobertura.ser";
056    
057            private static final Logger logger = Logger
058                            .getLogger(InstrumentationPersistence.class);
059    
060            final Map instrumentation = new HashMap();
061    
062            protected Map loadInstrumentation()
063            {
064                    File directory = getDirectory();
065    
066                    if (logger.isInfoEnabled())
067                    {
068                            logger.info("loading: " + directory + '/' + FILE_NAME);
069                    }
070    
071                    try
072                    {
073                            return loadInstrumentation(new FileInputStream(new File(
074                                            directory, FILE_NAME)));
075                    }
076                    catch (FileNotFoundException ex)
077                    {
078                            logger.info(ex);
079                            return Collections.EMPTY_MAP;
080                    }
081            }
082    
083            protected Map loadInstrumentation(InputStream is)
084            {
085                    ObjectInputStream objects = null;
086                    try
087                    {
088                            objects = new ObjectInputStream(is);
089                            Map m = (Map)objects.readObject();
090                            if (logger.isInfoEnabled())
091                            {
092                                    logger.info("loaded " + m.size() + " entries.");
093                            }
094                            return m;
095                    }
096                    catch (ClassNotFoundException ex)
097                    {
098                            logger.error(ex);
099                            return Collections.EMPTY_MAP;
100                    }
101                    catch (IOException ex)
102                    {
103                            logger.error(ex);
104                            return Collections.EMPTY_MAP;
105                    }
106                    finally
107                    {
108                            if (objects != null)
109                            {
110                                    try
111                                    {
112                                            objects.close();
113                                    }
114                                    catch (IOException ex)
115                                    {
116                                            if (logger.isDebugEnabled())
117                                            {
118                                                    logger.debug(ex);
119                                            }
120                                    }
121                            }
122    
123                            if (is != null)
124                            {
125                                    try
126                                    {
127                                            is.close();
128                                    }
129                                    catch (IOException ex)
130                                    {
131                                            if (logger.isDebugEnabled())
132                                            {
133                                                    logger.debug(ex);
134                                            }
135                                    }
136                            }
137                    }
138            }
139    
140            protected void merge(Map m)
141            {
142                    Iterator i = m.entrySet().iterator();
143                    while (i.hasNext())
144                    {
145                            Map.Entry entry = (Map.Entry)i.next();
146                            String classname = (String)entry.getKey();
147                            if (instrumentation.containsKey(classname))
148                            {
149                                    getInstrumentation(classname).merge(
150                                                    (CoverageData)entry.getValue());
151                            }
152                            else
153                            {
154                                    instrumentation.put(classname, entry.getValue());
155                            }
156                    }
157            }
158    
159            private File getDirectory()
160            {
161                    if (System.getProperty("net.sourceforge.cobertura.rawcoverage.dir") != null)
162                    {
163                            return new File(System
164                                            .getProperty("net.sourceforge.cobertura.rawcoverage.dir"));
165                    }
166                    return new File(System.getProperty("user.dir"));
167            }
168    
169            protected void saveInstrumentation()
170            {
171                    File directory = getDirectory();
172    
173                    if (logger.isInfoEnabled())
174                    {
175                            logger.info("saving: " + directory + '/' + FILE_NAME);
176                    }
177    
178                    saveInstrumentation(directory);
179            }
180    
181            protected void saveInstrumentation(File destDir)
182            {
183                    FileOutputStream os = null;
184                    ObjectOutputStream objects = null;
185    
186                    try
187                    {
188                            os = new FileOutputStream(new File(destDir, FILE_NAME));
189                            objects = new ObjectOutputStream(os);
190                            objects.writeObject(instrumentation);
191                            if (logger.isInfoEnabled())
192                            {
193                                    logger.info("saved " + instrumentation.size() + " entries.");
194                            }
195                    }
196                    catch (IOException ex)
197                    {
198                            logger.error(ex);
199                    }
200                    finally
201                    {
202                            if (objects != null)
203                            {
204                                    try
205                                    {
206                                            objects.close();
207                                    }
208                                    catch (IOException ex)
209                                    {
210                                            if (logger.isDebugEnabled())
211                                            {
212                                                    logger.debug(ex);
213                                            }
214                                    }
215                            }
216    
217                            if (os != null)
218                            {
219                                    try
220                                    {
221                                            os.close();
222                                    }
223                                    catch (IOException ex)
224                                    {
225                                            if (logger.isDebugEnabled())
226                                            {
227                                                    logger.debug(ex);
228                                            }
229                                    }
230                            }
231                    }
232            }
233    
234            protected CoverageData getInstrumentation(String classname)
235            {
236                    return (CoverageData)instrumentation.get(classname);
237            }
238    
239            protected Set keySet()
240            {
241                    return Collections.unmodifiableSet(instrumentation.keySet());
242            }
243    
244    }