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