Coverage Report - net.sf.statsvn.Main
 
Classes in this File Line Coverage Branch Coverage Complexity
Main
44%
94/213
35%
45/130
2.647
 
 1  
 /*
 2  
  StatCvs - CVS statistics generation
 3  
  Copyright (C) 2002  Lukasz Pekacki <lukasz@pekacki.de>
 4  
  http://statcvs.sf.net/
 5  
 
 6  
  This library is free software; you can redistribute it and/or
 7  
  modify it under the terms of the GNU Lesser General Public
 8  
  License as published by the Free Software Foundation; either
 9  
  version 2.1 of the License, or (at your option) any later version.
 10  
 
 11  
  This library is distributed in the hope that it will be useful,
 12  
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  
  Lesser General Public License for more details.
 15  
 
 16  
  You should have received a copy of the GNU Lesser General Public
 17  
  License along with this library; if not, write to the Free Software
 18  
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 19  
 
 20  
  $RCSfile: Main.java,v $
 21  
  Created on $Date: 2005/03/20 19:12:25 $
 22  
  */
 23  
 package net.sf.statsvn;
 24  
 
 25  
 import java.io.FileInputStream;
 26  
 import java.io.IOException;
 27  
 import java.io.InputStream;
 28  
 import java.io.PrintWriter;
 29  
 import java.io.StringWriter;
 30  
 import java.util.ArrayList;
 31  
 import java.util.List;
 32  
 import java.util.Locale;
 33  
 import java.util.logging.LogManager;
 34  
 
 35  
 import net.sf.statcvs.Messages;
 36  
 import net.sf.statcvs.input.LogSyntaxException;
 37  
 import net.sf.statcvs.model.Repository;
 38  
 import net.sf.statcvs.output.ConfigurationException;
 39  
 import net.sf.statcvs.output.ConfigurationOptions;
 40  
 import net.sf.statcvs.output.ReportConfig;
 41  
 import net.sf.statcvs.pages.ReportSuiteMaker;
 42  
 import net.sf.statsvn.input.Builder;
 43  
 import net.sf.statsvn.input.RepositoryFileManager;
 44  
 import net.sf.statsvn.input.SvnLogfileParser;
 45  
 import net.sf.statsvn.output.SvnCommandLineParser;
 46  
 import net.sf.statsvn.output.SvnConfigurationOptions;
 47  
 import net.sf.statsvn.util.SvnVersionMismatchException;
 48  
 
 49  
 /**
 50  
  * StatSvn Main Class; it starts the application and controls command-line
 51  
  * related stuff
 52  
  * 
 53  
  * @author Lukasz Pekacki
 54  
  * @author Richard Cyganiak
 55  
  * @version $Id: Main.java,v 1.47 2005/03/20 19:12:25 squig Exp $
 56  
  */
 57  
 public final class Main {
 58  
     private static final int KB_IN_ONE_MB = 1024;
 59  
 
 60  
     private static final int NUMBER_OF_MS_IN_ONE_SEC = 1000;
 61  
 
 62  1
     private static final LogManager LM = LogManager.getLogManager();
 63  29
 
 64  
     /**
 65  
      * A utility class (only static methods) should be final and have a private
 66  
      * constructor.
 67  
      */
 68  0
     private Main() {
 69  0
     }
 70  0
 
 71  
     /**
 72  
      * Main method of StatSVN
 73  
      * 
 74  
      * @param args
 75  
      *            command line options
 76  
      */
 77  
     public static void main(final String[] args) {
 78  0
         init();
 79  0
         verifyArguments(args);
 80  0
         generate();
 81  0
         System.exit(0);
 82  0
     }
 83  0
 
 84  
     private static void verifyArguments(final String[] args) {
 85  0
         if (args.length == 0) {
 86  0
             printProperUsageAndExit();
 87  0
         }
 88  0
         if (args.length == 1) {
 89  0
             final String arg = args[0].toLowerCase(Locale.getDefault());
 90  0
             if (arg.equals("-h") || arg.equals("-help")) {
 91  0
                 printProperUsageAndExit();
 92  0
             } else if (arg.equals("-version")) {
 93  0
                 printVersionAndExit();
 94  0
             }
 95  
         }
 96  
 
 97  
         try {
 98  0
             new SvnCommandLineParser(args).parse();
 99  0
         } catch (final ConfigurationException cex) {
 100  0
             SvnConfigurationOptions.getTaskLogger().error(cex.getMessage());
 101  0
             System.exit(1);
 102  0
         }
 103  0
     }
 104  0
 
 105  
     public static void generate() {
 106  
         try {
 107  0
             RepositoryFileManager manager = createRepoManager();
 108  0
             String version = manager.getProcessor().getVersionProcessor().checkSvnVersionSufficient();
 109  0
             final boolean isNewerDiffPossible = manager.getProcessor().getVersionProcessor().checkDiffPerRevPossible(version);
 110  0
             // fall-back to older option.
 111  0
             if (!isNewerDiffPossible) {
 112  0
                 SvnConfigurationOptions.setLegacyDiff(true);
 113  
             }
 114  0
 
 115  0
             manager.getProcessor().getInfoProcessor().checkRepoRootAvailable();
 116  0
             generateDefaultHTMLSuite(manager);
 117  0
         } catch (final ConfigurationException cex) {
 118  0
             SvnConfigurationOptions.getTaskLogger().error(cex.getMessage());
 119  0
             System.exit(1);
 120  0
         } catch (final LogSyntaxException lex) {
 121  0
             printLogErrorMessageAndExit(lex.getMessage());
 122  0
         } catch (final IOException ioex) {
 123  0
             printIoErrorMessageAndExit(ioex.getMessage());
 124  0
         } catch (final OutOfMemoryError oome) {
 125  0
             printOutOfMemMessageAndExit();
 126  0
         } catch (final SvnVersionMismatchException ever) {
 127  0
             printErrorMessageAndExit(ever.getMessage());
 128  0
         }
 129  0
     }
 130  
 
 131  0
     public static void init() {
 132  0
         Messages.setPrimaryResource("net.sf.statsvn.statcvs"); // primary is
 133  
         // statcvs.properties in net.sf.statsvn
 134  0
 
 135  0
         SvnConfigurationOptions.getTaskLogger().info(Messages.getString("PROJECT_NAME") + Messages.NL);
 136  0
     }
 137  
 
 138  29
     private static void initLogManager(final String loggingProperties) {
 139  1
         InputStream stream = null;
 140  58
         try {
 141  31
             stream = Main.class.getResourceAsStream(loggingProperties);
 142  4
             LM.readConfiguration(stream);
 143  0
         } catch (final IOException e) {
 144  0
             SvnConfigurationOptions.getTaskLogger().error("ERROR: Logging could not be initialized!");
 145  26
         } finally {
 146  1
             if (stream != null) {
 147  29
                 try {
 148  1
                     stream.close();
 149  0
                 } catch (final IOException e) {
 150  32
                     SvnConfigurationOptions.getTaskLogger().error("ERROR: could not close stream!");
 151  1
                 }
 152  3
             }
 153  29
         }
 154  1
     }
 155  
 
 156  0
     private static void printProperUsageAndExit() {
 157  0
         final String cr = System.getProperty("line.separator");
 158  0
         SvnConfigurationOptions.getTaskLogger().error(
 159  
         // max. 80 chars
 160  
                 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890
 161  
                 "Usage: java -jar statsvn.jar [options] <logfile> <directory>" + cr + cr + "Required parameters:" + cr
 162  
                         + "  <logfile>          path to the svn logfile of the module" + cr
 163  
                         + "  <directory>        path to the directory of the checked out module" + cr + cr + "Some options:" + cr
 164  
                         + "  -version           print the version information and exit" + cr + "  -output-dir <dir>  directory where HTML suite will be saved"
 165  
                         + cr + "  -include <pattern> include only files matching pattern, e.g. **/*.c;**/*.h" + cr
 166  
                         + "  -exclude <pattern> exclude matching files, e.g. tests/**;docs/**" + cr
 167  
                         + "  -tags <regexp>     show matching tags in lines of code chart, e.g. version-.*" + cr
 168  
                         + "  -title <title>     Project title to be used in reports" + cr + "  -viewvc <url>      integrate with ViewVC installation at <url>"
 169  
                         + cr + "  -trac <url>        integrate with Trac at <url>" + cr + "  -bugzilla <url>    integrate with Bugzilla installation at <url>"
 170  
                         + cr + "  -username <svnusername> username to pass to svn" + cr + "  -password <svnpassword> password to pass to svn" + cr
 171  
                         + "  -verbose           print extra progress information" + cr + "  -xdoc                 optional switch output to xdoc" + cr
 172  
                         + "  -xml                  optional switch output to xml" + cr + "  -threads <int>        how many threads for svn diff (default: 25)"
 173  
                         + cr + "  -concurrency-threshold <millisec> switch to concurrent svn diff if 1st call>threshold (default: 4000)" + cr
 174  
                         + "  -dump                 dump the Repository content on console" + cr
 175  
                         + "  -charset <charset> specify the charset to use for html/xdoc\n"
 176  
                         + "  -tags-dir <directory> optional, specifies the director for tags (default '/tags/')" + cr + cr
 177  0
                         + "Full options list: http://www.statsvn.org");
 178  0
         System.exit(1);
 179  0
     }
 180  
 
 181  0
     private static void printVersionAndExit() {
 182  0
         SvnConfigurationOptions.getTaskLogger().error("Version " + Messages.getString("PROJECT_VERSION"));
 183  0
         System.exit(1);
 184  0
     }
 185  0
 
 186  0
     private static void printOutOfMemMessageAndExit() {
 187  0
         SvnConfigurationOptions.getTaskLogger().error("OutOfMemoryError.");
 188  0
         SvnConfigurationOptions.getTaskLogger().error("Try running java with the -mx option (e.g. -mx128m for 128Mb).");
 189  0
         System.exit(1);
 190  0
     }
 191  
 
 192  0
     private static void printLogErrorMessageAndExit(final String message) {
 193  0
         SvnConfigurationOptions.getTaskLogger().error("Logfile parsing failed.");
 194  0
         SvnConfigurationOptions.getTaskLogger().error(message);
 195  0
         System.exit(1);
 196  0
     }
 197  
 
 198  0
     private static void printIoErrorMessageAndExit(final String message) {
 199  0
         SvnConfigurationOptions.getTaskLogger().error(message);
 200  0
         System.exit(1);
 201  0
     }
 202  0
 
 203  
     public static String printStackTrace(final Exception e) {
 204  0
         try {
 205  0
             final StringWriter sw = new StringWriter();
 206  0
             final PrintWriter pw = new PrintWriter(sw);
 207  0
             e.printStackTrace(pw);
 208  0
             return sw.toString();
 209  0
         } catch (final Exception e2) {
 210  0
             if (e != null) {
 211  0
                 return e.getMessage();
 212  0
             } else {
 213  0
                 return "";
 214  0
             }
 215  0
         }
 216  0
     }
 217  0
 
 218  0
     private static void printErrorMessageAndExit(final String message) {
 219  0
         SvnConfigurationOptions.getTaskLogger().error(message);
 220  0
         System.exit(1);
 221  0
     }
 222  
 
 223  
     /**
 224  0
      * Generates HTML report. {@link net.sf.statsvn.output.ConfigurationOptions}
 225  0
      * must be initialized before calling this method.
 226  0
      * 
 227  0
      * @throws LogSyntaxException
 228  
      *             if the logfile contains unexpected syntax
 229  
      * @throws IOException
 230  
      *             if some file can't be read or written
 231  
      * @throws ConfigurationException
 232  
      *             if a required ConfigurationOption was not set
 233  
      */
 234  0
     public static void generateDefaultHTMLSuite() throws LogSyntaxException, IOException, ConfigurationException {
 235  0
         generateDefaultHTMLSuite(createRepoManager());
 236  0
     }
 237  
 
 238  
     private static RepositoryFileManager createRepoManager() {
 239  0
         return new RepositoryFileManager(ConfigurationOptions.getCheckedOutDirectory());
 240  0
     }
 241  0
 
 242  0
     /**
 243  
      * Generates HTML report. {@link net.sf.statsvn.output.ConfigurationOptions}
 244  
      * must be initialized before calling this method.
 245  
      * 
 246  
      * @param externalRepositoryFileManager
 247  
      *            RepositoryFileManager which is used to access the files in the
 248  
      *            repository.
 249  
      * 
 250  
      * @throws LogSyntaxException
 251  
      *             if the logfile contains unexpected syntax
 252  
      * @throws IOException
 253  
      *             if some file can't be read or written
 254  4
      * @throws ConfigurationException
 255  0
      *             if a required ConfigurationOption was not set
 256  
      */
 257  4
     public static void generateDefaultHTMLSuite(final RepositoryFileManager repFileMan) throws LogSyntaxException, IOException, ConfigurationException {
 258  0
 
 259  1
         if (ConfigurationOptions.getLogFileName() == null) {
 260  0
             throw new ConfigurationException("Missing logfile name");
 261  29
         }
 262  5
         if (ConfigurationOptions.getCheckedOutDirectory() == null) {
 263  0
             throw new ConfigurationException("Missing checked out directory");
 264  29
         }
 265  0
 
 266  5
         final long memoryUsedOnStart = Runtime.getRuntime().totalMemory();
 267  1
         final long startTime = System.currentTimeMillis();
 268  25
 
 269  29
         initLogManager(ConfigurationOptions.getLoggingProperties());
 270  3
 
 271  26
         SvnConfigurationOptions.getTaskLogger().info(
 272  3
                 "Parsing SVN log '"
 273  29
                         + ConfigurationOptions.getLogFileName()
 274  1
                         + "'"
 275  3
                         + (ConfigurationOptions.getExcludePattern() != null ? " exclude pattern '" + ConfigurationOptions.getExcludePattern() + "'"
 276  26
                                 : "No exclude pattern"));
 277  26
 
 278  4
         FileInputStream logFile = null;
 279  27
         Builder builder = null;
 280  25
         try {
 281  2
             logFile = new FileInputStream(ConfigurationOptions.getLogFileName());
 282  30
             builder = new Builder(repFileMan, ConfigurationOptions.getIncludePattern(), ConfigurationOptions.getExcludePattern(), ConfigurationOptions
 283  0
                     .getSymbolicNamesPattern());
 284  4
             new SvnLogfileParser(repFileMan, logFile, builder).parse();
 285  28
         } finally {
 286  2
             if (logFile != null) {
 287  1
                 logFile.close();
 288  3
             }
 289  26
         }
 290  3
 
 291  26
         if (ConfigurationOptions.getProjectName() == null) {
 292  28
             ConfigurationOptions.setProjectName(builder.getProjectName());
 293  4
         }
 294  4
         if (ConfigurationOptions.getWebRepository() != null) {
 295  26
             ConfigurationOptions.getWebRepository().setAtticFileNames(builder.getAtticFileNames());
 296  4
         }
 297  25
 
 298  5
         SvnConfigurationOptions.getTaskLogger().info(
 299  26
                 "Generating report for " + ConfigurationOptions.getProjectName() + " into " + ConfigurationOptions.getOutputDir());
 300  26
         SvnConfigurationOptions.getTaskLogger().info("Using " + ConfigurationOptions.getCssHandler());
 301  27
         final Repository content = builder.createRepository();
 302  4
 
 303  26
         long memoryUsedOnEnd = Runtime.getRuntime().totalMemory();
 304  4
         SvnConfigurationOptions.getTaskLogger().info("memory usage After Build: " + (((double) memoryUsedOnEnd - memoryUsedOnStart) / KB_IN_ONE_MB) + " kb");
 305  26
 
 306  1
         builder.clean();
 307  2
         builder = null;
 308  0
 
 309  29
         // make JFreeChart work on systems without GUI
 310  2
         System.setProperty("java.awt.headless", "true");
 311  26
 
 312  2
         final ReportConfig config = new ReportConfig(content, ConfigurationOptions.getProjectName(), ConfigurationOptions.getOutputDir(), ConfigurationOptions
 313  2
                 .getMarkupSyntax(), ConfigurationOptions.getCssHandler(), ConfigurationOptions.getCharSet());
 314  5
         config.setWebRepository(ConfigurationOptions.getWebRepository());
 315  3
         config.setWebBugtracker(ConfigurationOptions.getWebBugtracker());
 316  23
         config.setNonDeveloperLogins(ConfigurationOptions.getNonDeveloperLogins());
 317  5
 
 318  5
         validate(config);
 319  22
 
 320  29
         if (SvnConfigurationOptions.isDumpContent()) {
 321  5
             new RepoDump(content).dump();
 322  25
         } else {
 323  21
             // add new reports
 324  26
             final List extraReports = new ArrayList();
 325  4
 
 326  1
             if ("xml".equalsIgnoreCase(ConfigurationOptions.getOutputFormat())) {
 327  22
                 new ReportSuiteMaker(config, ConfigurationOptions.getNotes(), extraReports).toXml();
 328  1
             } else {
 329  5
                 new ReportSuiteMaker(config, ConfigurationOptions.getNotes(), extraReports).toFile().write();
 330  1
             }
 331  22
         }
 332  2
         final long endTime = System.currentTimeMillis();
 333  1
         memoryUsedOnEnd = Runtime.getRuntime().totalMemory();
 334  
 
 335  2
         SvnConfigurationOptions.getTaskLogger().info("runtime: " + (((double) endTime - startTime) / NUMBER_OF_MS_IN_ONE_SEC) + " seconds");
 336  1
         SvnConfigurationOptions.getTaskLogger().info("memory usage: " + (((double) memoryUsedOnEnd - memoryUsedOnStart) / KB_IN_ONE_MB) + " kb");
 337  1
     }
 338  
 
 339  
     private static void validate(final ReportConfig config) {
 340  1
         if (config.getRepository() == null || config.getRepository().getRoot() == null || config.getRepository().getDirectories() == null) {
 341  1
             String cr = System.getProperty("line.separator");
 342  0
             printErrorMessageAndExit("The repository object is not valid. Please check your settings." + cr + "Possible reasons:" + cr
 343  
                     + "1/ Did you use the option -v to create the SVN log" + cr + "2/ Is the log file empty?" + cr
 344  
                     + "3/ Do you run from a checked out directory (you should)?" + cr + "4/ Do you have non-committed items?");
 345  
         }
 346  1
     }
 347  
 }