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.util.Timer;
026    
027    import org.apache.log4j.Logger;
028    
029    /**
030     * <p>
031     * This class implements HasBeenInstrumented so that when cobertura
032     * instruments itself, it will omit this class.  It does this to
033     * avoid an infinite recursion problem because instrumented classes
034     * make use of this class.
035     * </p>
036     */
037    public class CoverageDataFactory extends InstrumentationPersistence
038                    implements Runnable, HasBeenInstrumented
039    {
040    
041            private static final Logger logger = Logger
042                            .getLogger(CoverageDataFactory.class);
043            static final CoverageDataFactory instrumentationFactory = new CoverageDataFactory();
044    
045            Timer timer = new Timer(true);
046    
047            private CoverageDataFactory()
048            {
049                    merge(loadInstrumentation());
050    
051                    if (logger.isInfoEnabled())
052                    {
053                            logger.info("loaded: " + keySet().size() + " items.");
054                    }
055    
056                    /*
057                     * TODO:
058                     * I suspect this causes problems when
059                     * net.sourceforge.cobertura.instrumentation.interval
060                     * is not equal to 0.  It seems like it deletes cobertura.ser just as
061                     * it begins running the first test.  So then we only have coverage
062                     * data about the lines we tests.  Also, attempting to load this as
063                     * we begin testing prints an ugly file not found exception... Hmm,
064                     * what's going on here?  It should load with no problems, I think.
065                     * It looks like it's trying to load the file from the wrong place,
066                     * or something.
067                     */
068                    if (getInstrumentationInterval() > 0)
069                    {
070                            timer.schedule(new SaveInstrumentationTimer(this),
071                                            getInstrumentationInterval(),
072                                            getInstrumentationInterval());
073                    }
074    
075                    Runtime.getRuntime().addShutdownHook(new Thread(this));
076            }
077    
078            int getInstrumentationInterval()
079            {
080                    return Integer.getInteger(
081                                    "net.sourceforge.cobertura.instrumentation.interval", 0)
082                                    .intValue() * 1000;
083            }
084    
085            public void run()
086            {
087                    if (logger.isInfoEnabled())
088                    {
089                            logger.info("shutdown hook started");
090                    }
091    
092                    saveInstrumentation();
093    
094                    if (logger.isInfoEnabled())
095                    {
096                            logger.info("saved: " + keySet().size() + " items.");
097                    }
098    
099                    if (logger.isInfoEnabled())
100                    {
101                            logger.info("shutdown hook has finished");
102                    }
103            }
104    
105            public static CoverageDataFactory getInstance()
106            {
107                    return instrumentationFactory;
108            }
109    
110            public CoverageData newInstrumentation(String className)
111            {
112                    if (!instrumentation.containsKey(className))
113                    {
114                            instrumentation.put(className, new CoverageData());
115                    }
116                    return (CoverageData)instrumentation.get(className);
117            }
118    }