View Javadoc

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: ConfigurationOptions.java,v $
21  	$Date: 2009/03/13 23:04:28 $ 
22  */
23  package net.sf.statcvs.output;
24  
25  import java.awt.Color;
26  import java.io.BufferedReader;
27  import java.io.File;
28  import java.io.FileInputStream;
29  import java.io.FileNotFoundException;
30  import java.io.FileReader;
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.net.MalformedURLException;
34  import java.net.URL;
35  import java.util.ArrayList;
36  import java.util.Collection;
37  import java.util.Properties;
38  import java.util.regex.Pattern;
39  import java.util.regex.PatternSyntaxException;
40  
41  import net.sf.statcvs.pages.MarkupSyntax;
42  import net.sf.statcvs.util.FilePatternMatcher;
43  import net.sf.statcvs.util.FileUtils;
44  import net.sf.statcvs.weblinks.bugs.BugTracker;
45  import net.sf.statcvs.weblinks.bugs.Bugzilla;
46  import net.sf.statcvs.weblinks.bugs.Mantis;
47  
48  import org.jfree.chart.renderer.category.BarRenderer;
49  import org.jfree.chart.renderer.category.StandardBarPainter;
50  import org.jfree.chart.renderer.xy.StandardXYBarPainter;
51  import org.jfree.chart.renderer.xy.XYBarRenderer;
52  
53  /**
54   * Class for storing all command line parameters. The parameters
55   * are set by the {@link net.sf.statcvs.Main#main} method. Interested classes
56   * can read all parameter values from here.
57   * 
58   * TODO: Should be moved to more appropriate package and made non-public
59   * 
60   * @author jentzsch
61   * @version $Id: ConfigurationOptions.java,v 1.37 2009/03/13 23:04:28 benoitx Exp $
62   */
63  public class ConfigurationOptions {
64  
65      private static final String LOGGING_CONFIG_DEFAULT = "logging.properties";
66      private static final String LOGGING_CONFIG_VERBOSE = "logging-verbose.properties";
67      private static final String LOGGING_CONFIG_DEBUG = "logging-debug.properties";
68  
69      private static String logFileName = null;
70      private static String checkedOutDirectory = null;
71      private static String projectName = null;
72      private static String outputDir = "";
73      private static String loggingProperties = LOGGING_CONFIG_DEFAULT;
74      private static String notesFile = null;
75      private static String notes = null;
76  
77      private static FilePatternMatcher includePattern = null;
78      private static FilePatternMatcher excludePattern = null;
79  
80      private static Collection nonDeveloperLogins = new ArrayList();
81  
82      private static CssHandler cssHandler = new DefaultCssHandler("objectlab-statcvs.css");
83      private static String charSet = "ISO-8859-1";
84      private static WebRepositoryIntegration webRepository = null;
85      private static Pattern symbolicNamesPattern;
86  
87      private static BugTracker webBugTracker = BugTracker.NO_BUG_TRACKER;
88      private static String outputFormat = "html";
89      private static Properties properties = new Properties();
90  
91      static {
92          XYBarRenderer.setDefaultBarPainter(new StandardXYBarPainter());
93          BarRenderer.setDefaultBarPainter(new StandardBarPainter());
94      }
95  
96      public static String getCharSet() {
97          return charSet;
98      }
99  
100     public static void setCharSet(final String cs) {
101         charSet = cs;
102     }
103 
104     /**
105      * returns the {@link CssHandler}
106      * @return the CssHandler
107      */
108     public static CssHandler getCssHandler() {
109         return cssHandler;
110     }
111 
112     /**
113      * Method getProjectName.
114      * @return String name of the project
115      */
116     public static String getProjectName() {
117         return projectName;
118     }
119 
120     /**
121      * Method getCheckedOutDirectory.
122      * @return String name of the checked out directory
123      */
124     public static String getCheckedOutDirectory() {
125         return checkedOutDirectory;
126     }
127 
128     /**
129      * Method getLogfilename.
130      * @return String name of the logfile to be parsed
131      */
132     public static String getLogFileName() {
133         return logFileName;
134     }
135 
136     /**
137      * Returns the outputDir.
138      * @return String output Directory
139      */
140     public static String getOutputDir() {
141         return outputDir;
142     }
143 
144     /**
145      * Returns the report notes (from "-notes filename" switch) or <tt>null</tt>
146      * if not specified
147      * @return the report notes
148      */
149     public static String getNotes() {
150         return notes;
151     }
152 
153     /**
154      * Returns a {@link WebRepositoryIntegration} object if the user
155      * has specified a URL to one. <tt>null</tt> otherwise.
156      * @return the web repository
157      */
158     public static WebRepositoryIntegration getWebRepository() {
159         return webRepository;
160     }
161 
162     /**
163      * Sets the checkedOutDirectory.
164      * @param checkedOutDirectory The checkedOutDirectory to set
165      * @throws ConfigurationException if directory does not exist
166      */
167     public static void setCheckedOutDirectory(final String checkedOutDirectory) throws ConfigurationException {
168         final File directory = new File(checkedOutDirectory);
169         if (!directory.exists() || !directory.isDirectory()) {
170             throw new ConfigurationException("directory does not exist: " + checkedOutDirectory);
171         }
172         ConfigurationOptions.checkedOutDirectory = checkedOutDirectory;
173     }
174 
175     /**
176      * Sets the cssFile. Currently, the css file can be any local file or
177      * a HTTP URL. If it is a local file, a copy will be included in the
178      * output directory. If this method is never called, a default CSS file
179      * will be generated in the output directory.
180      *
181      * @param cssFile The cssFile to set
182      * @throws ConfigurationException if the specified CSS file can not be
183      * accessed from local file system or from URL source, or if the specified
184      * CSS file is local and does not exist
185      */
186     public static void setCssFile(final String cssFile) throws ConfigurationException {
187         try {
188             final URL url = new URL(cssFile);
189             if (!url.getProtocol().equals("http")) {
190                 throw new ConfigurationException("Only HTTP URLs or local files allowed for -css");
191             }
192             cssHandler = new UrlCssHandler(url);
193         } catch (final MalformedURLException isLocalFile) {
194             cssHandler = new LocalFileCssHandler(cssFile);
195         }
196         cssHandler.checkForMissingResources();
197     }
198 
199     /**
200      * Sets the logFileName.
201      * @param logFileName The logFileName to set
202      * @throws ConfigurationException if the file does not exist
203      */
204     public static void setLogFileName(final String logFileName) throws ConfigurationException {
205         final File inputFile = new File(logFileName);
206         if (!inputFile.exists()) {
207             throw new ConfigurationException("Specified logfile not found: " + logFileName);
208         }
209         ConfigurationOptions.logFileName = logFileName;
210     }
211 
212     /**
213      * Sets the outputDir.
214      * @param outputDir The outputDir to set
215      * @throws ConfigurationException if the output directory cannot be created
216      */
217     public static void setOutputDir(String outputDir) throws ConfigurationException {
218         if (!outputDir.endsWith(FileUtils.getDirSeparator())) {
219             outputDir += FileUtils.getDefaultDirSeparator();
220         }
221         final File outDir = new File(outputDir);
222         if (!outDir.exists() && !outDir.mkdirs()) {
223             throw new ConfigurationException("Can't create output directory: " + outputDir);
224         }
225         ConfigurationOptions.outputDir = outputDir;
226     }
227 
228     /**
229      * Sets the name of the notes file. The notes file will be included
230      * on the index page of the output. It must contain a valid
231      * block-level HTML fragment (for example
232      * <tt>"&lt;p&gt;Some notes&lt;/p&gt;"</tt>) 
233      * @param notesFile a local filename
234      * @throws ConfigurationException if the file is not found or can't be read
235      */
236     public static void setNotesFile(final String notesFile) throws ConfigurationException {
237         final File f = new File(notesFile);
238         if (!f.exists()) {
239             throw new ConfigurationException("Notes file not found: " + notesFile);
240         }
241         if (!f.canRead()) {
242             throw new ConfigurationException("Can't read notes file: " + notesFile);
243         }
244         ConfigurationOptions.notesFile = notesFile;
245         try {
246             notes = readNotesFile();
247         } catch (final IOException e) {
248             throw new ConfigurationException(e.getMessage());
249         }
250     }
251 
252     /**
253      * Sets the URL to a <a href="http://viewcvs.sourceforge.net/">ViewCVS</a>
254      * web-based CVS browser. This must be the URL at which the checked-out
255      * module's root can be viewed in ViewCVS.
256      * @param url URL to a ViewCVS repository
257      */
258     public static void setViewCvsURL(final String url) {
259         ConfigurationOptions.webRepository = new ViewCvsIntegration(url);
260     }
261 
262     /**
263      * Sets the URL to a 
264      * <a href="http://www.freebsd.org/projects/cvsweb.html">cvsweb</a>
265      * web-based CVS browser. This must be the URL at which the checked-out
266      * module's root can be viewed in cvsweb.
267      * @param url URL to a cvsweb repository
268      */
269     public static void setCvswebURL(final String url) {
270         ConfigurationOptions.webRepository = new CvswebIntegration(url);
271     }
272 
273     /**
274      * Sets the URL to a <a href="http://www.horde.org/chora/">Chora</a>
275      * web-based CVS browser. This must be the URL at which the checked-out
276      * module's root can be viewed in Chora.
277      * @param url URL to a cvsweb repository
278      */
279     public static void setChoraURL(final String url) {
280         ConfigurationOptions.webRepository = new ChoraIntegration(url);
281     }
282 
283     /**
284      * Sets the URL to a <a href="http://www.jcvs.org/jcvsweb/">JCVSWeb</a>
285      * web-based CVS browser. This must be the URL at which the checked-out
286      * module's root can be viewed in JCVSWeb.
287      * @param url URL to a JCVSWeb repository
288      */
289     public static void setJCVSWebURL(final String url) {
290         ConfigurationOptions.webRepository = new JCVSWebIntegration(url);
291     }
292 
293     /**
294      * Sets the URL to a <a href="http://www.viewvc.org/">ViewVC</a> web-based CVS/SVN browser. 
295      * This must be the URL at which the checked-out module's
296      * root can be viewed in ViewVC.
297      * 
298      * @param url
299      *            URL to a ViewVC repository
300      */
301     public static void setViewVcURL(final String url) {
302         ConfigurationOptions.webRepository = new ViewVcIntegration(url);
303     }
304 
305     /**
306      * Sets the URL to a <a href="http://trac.edgewall.org/wiki/TracBrowser">Trac</a> web-based SVN browser and issue tracking. 
307      * This must be the URL at which the checked-out module's
308      * root can be viewed in Trac 
309      * 
310      * @param url
311      *            URL to a Trac website
312      */
313     public static void setViewTracURL(final String url) {
314         ConfigurationOptions.webRepository = new TracIntegration(url);
315     }
316 
317     /**
318      * Sets a project title to be used in the reports
319      * @param projectName The project title to be used in the reports
320      */
321     public static void setProjectName(final String projectName) {
322         ConfigurationOptions.projectName = projectName;
323     }
324 
325     /**
326      * Gets the name of the logging properties file
327      * @return the name of the logging properties file
328      */
329     public static String getLoggingProperties() {
330         return loggingProperties;
331     }
332 
333     /**
334      * Sets the logging level to verbose
335      */
336     public static void setVerboseLogging() {
337         ConfigurationOptions.loggingProperties = LOGGING_CONFIG_VERBOSE;
338     }
339 
340     /**
341      * Sets the logging level to debug
342      */
343     public static void setDebugLogging() {
344         ConfigurationOptions.loggingProperties = LOGGING_CONFIG_DEBUG;
345     }
346 
347     private static String readNotesFile() throws IOException {
348         BufferedReader r = null;
349         final StringBuffer result = new StringBuffer();
350         try {
351             r = new BufferedReader(new FileReader(notesFile));
352             String line = r.readLine();
353             while (line != null) {
354                 result.append(line);
355                 line = r.readLine();
356             }
357         } finally {
358             if (r != null) {
359                 r.close();
360             }
361         }
362         return result.toString();
363     }
364 
365     /**
366      * Sets a file include pattern list. Only files matching one of the
367      * patterns will be included in the analysis.
368      * @param patternList a list of Ant-style wildcard patterns, seperated
369      *                    by : or ;
370      * @see net.sf.statcvs.util.FilePatternMatcher
371      */
372     public static void setIncludePattern(final String patternList) {
373         includePattern = new FilePatternMatcher(patternList);
374     }
375 
376     /**
377      * Sets a file exclude pattern list. Files matching any of the
378      * patterns will be excluded from the analysis.
379      * @param patternList a list of Ant-style wildcard patterns, seperated
380      *                    by : or ;
381      * @see net.sf.statcvs.util.FilePatternMatcher
382      */
383     public static void setExcludePattern(final String patternList) {
384         excludePattern = new FilePatternMatcher(patternList);
385     }
386 
387     /**
388      * @return Returns the excludePattern.
389      */
390     public static FilePatternMatcher getExcludePattern() {
391         return excludePattern;
392     }
393 
394     /**
395      * @return Returns the includePattern.
396      */
397     public static FilePatternMatcher getIncludePattern() {
398         return includePattern;
399     }
400 
401     public static void setSymbolicNamesPattern(final String symbolicNamesPattern) throws ConfigurationException {
402         try {
403             ConfigurationOptions.symbolicNamesPattern = Pattern.compile(symbolicNamesPattern);
404         } catch (final PatternSyntaxException e) {
405             throw new ConfigurationException("Invalid regular expression for tags: " + e.getLocalizedMessage());
406         }
407     }
408 
409     public static Pattern getSymbolicNamesPattern() {
410         return symbolicNamesPattern;
411     }
412 
413     public static void setBugzillaUrl(final String bugzillaUrl) {
414         ConfigurationOptions.webBugTracker = new Bugzilla(bugzillaUrl);
415     }
416 
417     public static void setMantisUrl(final String mantisUrl) {
418         ConfigurationOptions.webBugTracker = new Mantis(mantisUrl);
419     }
420 
421     public static BugTracker getWebBugtracker() {
422         return ConfigurationOptions.webBugTracker;
423     }
424 
425     public static void setOutputFormat(final String outputFormat) throws ConfigurationException {
426         if (!"html".equals(outputFormat) && !"xdoc".equals(outputFormat) && !"xml".equals(outputFormat)) {
427             throw new ConfigurationException("Invalid output format, use only 'html', 'xdoc' or 'xml'");
428         }
429         ConfigurationOptions.outputFormat = outputFormat;
430     }
431 
432     public static String getOutputFormat() {
433         return outputFormat;
434     }
435 
436     public static MarkupSyntax getMarkupSyntax() {
437         if ("xdoc".equals(outputFormat)) {
438             return ReportConfig.XDOC;
439         } else if ("xml".equals(outputFormat)) {
440             return ReportConfig.XML;
441         }
442         return ReportConfig.HTML;
443     }
444 
445     public static void setWebRepositoryIntegration(final WebRepositoryIntegration webRepo) {
446         webRepository = webRepo;
447     }
448 
449     /**
450     * Allow change between css that are shipped with the tool.
451     * @param cssName statcvs.css or objectlab-statcvs-xdoc.css
452     */
453     public static void setDefaultCssFile(final String cssName) {
454         cssHandler = new DefaultCssHandler(cssName);
455     }
456 
457     /**
458      * Excludes a login name from charts and reports that compare
459      * several developers. Useful to reduce the noise from admin
460      * accounts.
461      * @param loginName A login name
462      */
463     public static void addNonDeveloperLogin(final String loginName) {
464         nonDeveloperLogins.add(loginName);
465     }
466 
467     /**
468      * Gets login names that should be excluded from charts and
469      * reports that compare several developers.
470      */
471     public static Collection getNonDeveloperLogins() {
472         return nonDeveloperLogins;
473     }
474 
475     /**
476      * Set the config file that may contain user details.
477      * @param propertiesFilename
478      */
479     public static void setConfigFile(final String propertiesFilename) throws ConfigurationException {
480         if (propertiesFilename != null) {
481             InputStream is = null;
482             try {
483                 is = new FileInputStream(propertiesFilename);
484                 properties.load(is);
485             } catch (final FileNotFoundException e) {
486                 throw new ConfigurationException("Unable to find the configuration file " + propertiesFilename);
487             } catch (final IOException e) {
488                 throw new ConfigurationException("Problem reading the configuration file " + propertiesFilename);
489             } finally {
490                 if (is != null) {
491                     try {
492                         is.close();
493                     } catch (final IOException e) {
494                         throw new ConfigurationException("Problem closing stream to the configuration file " + propertiesFilename);
495                     }
496                 }
497             }
498         }
499     }
500 
501     /**
502      * The config properties.
503      * @return
504      */
505     public static Properties getConfigProperties() {
506         return properties;
507     }
508 
509     /**
510      * Return a String prop.
511      * @param propName
512      * @param defaultValue
513      * @return
514      */
515     public static String getConfigStringProperty(final String propName, final String defaultValue) {
516         if (properties != null) {
517             return properties.getProperty(propName, defaultValue);
518         }
519         return defaultValue;
520     }
521 
522     public static String getConfigStringProperty(final String propName, final String fallBackPropName, final String defaultValue) {
523         if (properties != null) {
524             final String val = properties.getProperty(propName);
525             if (val != null) {
526                 return val;
527             } else {
528                 return properties.getProperty(fallBackPropName, defaultValue);
529             }
530         }
531         return defaultValue;
532     }
533 
534     /**
535      * Return a Integer prop.
536      * @param propName
537      * @param defaultValue
538      * @return
539      */
540     public static Integer getConfigIntegerProperty(final String propName, final Integer defaultValue) {
541         if (properties != null) {
542             final String val = properties.getProperty(propName);
543             if (val != null) {
544                 try {
545                     return Integer.valueOf(val);
546                 } catch (final NumberFormatException e) {
547                     return defaultValue;
548                 }
549             }
550         }
551         return defaultValue;
552     }
553 
554     /**
555      * Return a Float prop.
556      * @param propName
557      * @param defaultValue
558      * @return
559      */
560     public static Float getConfigIntegerProperty(final String propName, final Float defaultValue) {
561         if (properties != null) {
562             final String val = properties.getProperty(propName);
563             if (val != null) {
564                 try {
565                     return Float.valueOf(val);
566                 } catch (final NumberFormatException e) {
567                     return defaultValue;
568                 }
569             }
570         }
571         return defaultValue;
572     }
573 
574     /**
575      * Return a String prop.
576      * @param propName
577      * @param defaultValue
578      * @return
579      */
580     public static Color getConfigColorProperty(final String propName, final Color defaultValue) {
581         if (properties != null) {
582             String val = properties.getProperty(propName);
583             if (val != null) {
584                 if (val.startsWith("#")) {
585                     val = val.substring(1);
586                 }
587                 val = val.toLowerCase();
588                 if (val.length() > 6) {
589                     return defaultValue;
590                 }
591                 return new Color(Integer.parseInt(val, 16));
592             }
593         }
594         return defaultValue;
595     }
596 
597     /**
598      * Return a Integer prop.
599      * @param propName
600      * @param defaultValue
601      * @return
602      */
603     public static Integer getConfigIntegerProperty(final String propName, final String fallBackPropName, final Integer defaultValue) {
604         if (properties != null) {
605             final String val = properties.getProperty(propName);
606             if (val != null) {
607                 try {
608                     return Integer.valueOf(val);
609                 } catch (final NumberFormatException e) {
610                     return defaultValue;
611                 }
612             } else {
613                 return getConfigIntegerProperty(fallBackPropName, defaultValue);
614             }
615         }
616         return defaultValue;
617     }
618 
619     /**
620      * Return a Float prop.
621      * @param propName
622      * @param defaultValue
623      * @return
624      */
625     public static Float getConfigFloatProperty(final String propName, final String fallBackPropName, final Float defaultValue) {
626         if (properties != null) {
627             final String val = properties.getProperty(propName);
628             if (val != null) {
629                 try {
630                     return Float.valueOf(val);
631                 } catch (final NumberFormatException e) {
632                     return defaultValue;
633                 }
634             } else {
635                 return getConfigIntegerProperty(fallBackPropName, defaultValue);
636             }
637         }
638         return defaultValue;
639     }
640 
641     /**
642      * Return a Boolean prop.
643      * @param propName
644      * @param defaultValue
645      * @return
646      */
647     public static Boolean getConfigBooleanProperty(final String propName, final String fallBackPropName, final Boolean defaultValue) {
648         if (properties != null) {
649             String val = properties.getProperty(propName);
650             if (val != null) {
651                 try {
652                     return Boolean.valueOf(val);
653                 } catch (final NumberFormatException e) {
654                     return defaultValue;
655                 }
656             } else {
657                 val = properties.getProperty(fallBackPropName);
658                 if (val != null) {
659                     return Boolean.valueOf(val);
660                 }
661             }
662         }
663         return defaultValue;
664     }
665 
666     /**
667      * Return a Color prop.
668      * @param propName
669      * @param defaultValue
670      * @return
671      */
672     public static Color getConfigColorProperty(final String propName, final String fallBackPropName, final Color defaultValue) {
673         if (properties != null) {
674             String val = properties.getProperty(propName);
675             if (val != null) {
676                 if (val.startsWith("#")) {
677                     val = val.substring(1);
678                 }
679                 val = val.toLowerCase();
680                 if (val.length() > 6) {
681                     return defaultValue;
682                 }
683                 return new Color(Integer.parseInt(val, 16));
684             } else {
685                 return getConfigColorProperty(fallBackPropName, defaultValue);
686             }
687         }
688         return defaultValue;
689     }
690 }