1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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>"<p>Some notes</p>"</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 }