001: /*
002: * Hammurapi
003: * Automated Java code review system.
004: * Copyright (C) 2004 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.org
021: * e-Mail: support@hammurapi.biz
022: */
023: package org.hammurapi;
024:
025: import java.io.File;
026: import java.io.FileNotFoundException;
027: import java.io.IOException;
028: import java.io.InputStreamReader;
029: import java.net.InetAddress;
030: import java.sql.SQLException;
031: import java.text.SimpleDateFormat;
032: import java.util.Collection;
033: import java.util.Date;
034: import java.util.Iterator;
035: import java.util.LinkedList;
036: import java.util.List;
037:
038: import org.apache.commons.cli.CommandLine;
039: import org.apache.commons.cli.CommandLineParser;
040: import org.apache.commons.cli.Option;
041: import org.apache.commons.cli.OptionBuilder;
042: import org.apache.commons.cli.Options;
043: import org.apache.commons.cli.ParseException;
044: import org.apache.commons.cli.PosixParser;
045: import org.apache.tools.ant.AntClassLoader;
046: import org.apache.tools.ant.BuildException;
047: import org.apache.tools.ant.DirectoryScanner;
048: import org.apache.tools.ant.Project;
049: import org.hammurapi.results.CompositeResults;
050: import org.hammurapi.results.persistent.jdbc.ResultsFactory;
051: import org.hammurapi.results.persistent.jdbc.ResultsFactoryConfig;
052: import org.w3c.dom.Element;
053:
054: import com.pavelvlasov.ant.ConnectionEntry;
055: import com.pavelvlasov.config.Component;
056: import com.pavelvlasov.config.ConfigurationException;
057: import com.pavelvlasov.jsel.JselException;
058: import com.pavelvlasov.jsel.Repository;
059: import com.pavelvlasov.jsel.RevisionMapper;
060: import com.pavelvlasov.jsel.impl.DbRepositoryImpl;
061: import com.pavelvlasov.jsel.impl.RepositoryConfig;
062: import com.pavelvlasov.jsel.impl.WarningSink;
063: import com.pavelvlasov.logging.AntLogger;
064: import com.pavelvlasov.logging.Logger;
065: import com.pavelvlasov.metrics.MeasurementCategoryFactory;
066: import com.pavelvlasov.metrics.TimeIntervalCategory;
067: import com.pavelvlasov.persistence.CompositeStorage;
068: import com.pavelvlasov.persistence.FileStorage;
069: import com.pavelvlasov.persistence.MemoryStorage;
070: import com.pavelvlasov.render.RenderingException;
071: import com.pavelvlasov.review.SimpleSourceMarker;
072: import com.pavelvlasov.review.SourceMarker;
073: import com.pavelvlasov.review.SourceMarkerComparator;
074: import com.pavelvlasov.sql.ConnectionPerThreadDataSource;
075: import com.pavelvlasov.sql.DataAccessObject;
076: import com.pavelvlasov.sql.JdbcStorage;
077: import com.pavelvlasov.sql.SQLProcessor;
078: import com.pavelvlasov.sql.Transaction;
079: import com.pavelvlasov.sql.hypersonic.HypersonicServerDataSource;
080: import com.pavelvlasov.sql.hypersonic.HypersonicStandaloneDataSource;
081: import com.pavelvlasov.sql.hypersonic.HypersonicTmpDataSource;
082: import com.pavelvlasov.util.VisitorStack;
083: import com.pavelvlasov.util.VisitorStackSource;
084:
085: /**
086: * Performs automatic code reviews.
087: * <section name="Example" suppress-description="yes">
088: If you copy content of Hammurapi lib directory to ant lib directory then you can
089: invoke Hammurapi in the following way:
090: <pre>
091: <taskdef name="hammurapi" classname="org.hammurapi.HammurapiTask" /><br/>
092: <br/>
093: <hammurapi><br/>
094: <tab/><src dir="src"/><br/>
095: <tab/><output dir="review"/><br/>
096: </hammurapi></pre>
097: or, if you didn't copy jar files to Ant lib directory, use this syntax:
098: <pre>
099: <taskdef name="hammurapi" classname="org.hammurapi.HammurapiTask"><br/>
100: <tab/><classpath><br/>
101: <tab/><tab/><fileset dir="${hammurapi.home}/lib" includes="*.jar"/><br/>
102: <tab/></classpath><br/>
103: </taskdef><br/>
104: <br/>
105: <hammurapi><br/>
106: <tab/><src dir="src"/><br/>
107: <tab/><output dir="review"/><br/>
108: </hammurapi>
109: </pre>
110:
111: </section>
112: * @ant.element name="hammurapi" display-name="Automatic code review task"
113: * @author Pavel Vlasov
114: * @version $Revision: 1.25 $
115: */
116: public class HammurapiTask extends TaskBase {
117:
118: /**
119: * Helper class to start/stop violation filters
120: * @author Pavel Vlasov
121: * @revision $Revision: 1.25 $
122: */
123: public class ViolationFilterVisitor {
124: public void visit(Repository repo)
125: throws ConfigurationException {
126: // Initializing violation filters
127: Iterator vfit = violationFilters.iterator();
128: while (vfit.hasNext()) {
129: Object vf = vfit.next();
130: if (vf instanceof Component) {
131: ((Component) vf).start();
132: }
133: }
134: }
135:
136: public void leave(Repository repo)
137: throws ConfigurationException {
138: // Stopping violation filters
139: Iterator vfit = violationFilters.iterator();
140: while (vfit.hasNext()) {
141: Object vf = vfit.next();
142: if (vf instanceof Component) {
143: ((Component) vf).stop();
144: }
145: }
146: }
147: }
148:
149: private static final TimeIntervalCategory tic = MeasurementCategoryFactory
150: .getTimeIntervalCategory(HammurapiTask.class);
151:
152: private boolean wrap = false;
153:
154: private boolean cleanup = true;
155: boolean skipIntactPackages = false;
156:
157: private boolean forceOnWaivers;
158:
159: /**
160: * Cleanup old reviews info after review.
161: * Defaults to 'true'.
162: * @ant.non-required
163: * @param cleanup
164: */
165: public void setCleanup(boolean cleanup) {
166: this .cleanup = cleanup;
167: }
168:
169: /**
170: * Do not generate summary pages for packages and summary
171: * if no files were changed in package/summary.
172: * Set it to 'true' to improve performance if you don not use
173: * 'New' marker on modified files.
174: * @ant.non-required
175: * @param skipIntactPackages
176: */
177: public void setSkipIntactPackages(boolean skipIntactPackages) {
178: this .skipIntactPackages = skipIntactPackages;
179: }
180:
181: /**
182: * Force review of compilation units for which waivers are available.
183: * Default is true.
184: * @ant.non-required.
185: */
186: public void setForceOnWaivers(boolean forceOnWaivers) {
187: this .forceOnWaivers = forceOnWaivers;
188: }
189:
190: boolean isForceOnWaivers() {
191: return forceOnWaivers;
192: }
193:
194: private Date baseLine;
195:
196: /**
197: * Date of baseline report
198: * @ant.non-required
199: * @param baseLine
200: */
201: public void setBaseLine(Date baseLine) {
202: this .baseLine = baseLine;
203: }
204:
205: private String hostId;
206:
207: public void execute() throws BuildException {
208: long started = System.currentTimeMillis();
209:
210: if (!suppressLogo) {
211: log("Hammurapi 3 Copyright (C) 2004 Hammurapi Group");
212: }
213:
214: File archiveTmpDir = processArchive();
215:
216: try {
217: Logger logger = new AntLogger(this );
218:
219: final VisitorStack[] visitorStack = { null };
220: final VisitorStackSource visitorStackSource = new VisitorStackSource() {
221: public VisitorStack getVisitorStack() {
222: return visitorStack[0];
223: }
224: };
225:
226: final SessionImpl reviewSession = new SessionImpl();
227:
228: InspectorSet inspectorSet = new InspectorSet(
229: new InspectorContextFactory() {
230: public InspectorContext newContext(
231: InspectorDescriptor descriptor,
232: Logger logger) {
233: return new InspectorContextImpl(descriptor,
234: logger, visitorStackSource,
235: reviewSession, violationFilters);
236: }
237: }, logger);
238:
239: if (embeddedInspectors) {
240: log("Loading embedded inspectors", Project.MSG_VERBOSE);
241: loadEmbeddedInspectors(inspectorSet);
242: }
243:
244: log("Loading inspectors", Project.MSG_VERBOSE);
245: Iterator it = inspectors.iterator();
246: while (it.hasNext()) {
247: Object o = it.next();
248: if (o instanceof InspectorSource) {
249: ((InspectorSource) o).loadInspectors(inspectorSet);
250: } else {
251: InspectorEntry inspectorEntry = (InspectorEntry) o;
252: inspectorSet.addDescriptor(inspectorEntry);
253: inspectorSet
254: .addInspectorSourceInfo(new InspectorSourceInfo(
255: "Inline inspector "
256: + inspectorEntry.getName(),
257: "Build file: "
258: + inspectorEntry
259: .getLocation()
260: .toString(), ""));
261: }
262: }
263:
264: log("Inspectors loaded: " + inspectorSet.size(),
265: Project.MSG_VERBOSE);
266:
267: log("Loading waivers", Project.MSG_VERBOSE);
268: Date now = new Date();
269: WaiverSet waiverSet = new WaiverSet();
270: it = waivers.iterator();
271: while (it.hasNext()) {
272: ((WaiverSource) it.next()).loadWaivers(waiverSet, now);
273: }
274:
275: log("Waivers loaded: " + waiverSet.size(),
276: Project.MSG_VERBOSE);
277:
278: log("Loading listeners", Project.MSG_VERBOSE);
279: List listeners = new LinkedList();
280: it = listenerEntries.iterator();
281: while (it.hasNext()) {
282: listeners.add(((ListenerEntry) it.next())
283: .getObject(null));
284: }
285:
286: //Outputs
287: listeners.addAll(outputs);
288: listeners.add(new ReviewToLogListener(project));
289:
290: log("Loading source files", Project.MSG_VERBOSE);
291:
292: RepositoryConfig config = new RepositoryConfig();
293: if (classPath != null) {
294: log("Loading class files to repository",
295: Project.MSG_DEBUG);
296: config.setClassLoader(new AntClassLoader(project,
297: classPath, false));
298: reviewSession.setClassPath(classPath.list());
299: }
300:
301: config.setLogger(logger);
302: config.setCalculateDependencies(calculateDependencies);
303: config.setStoreSource(storeSource);
304: config.setEncoding(getEncoding());
305:
306: it = srcFileSets.iterator();
307: while (it.hasNext()) {
308: HammurapiFileSet fs = (HammurapiFileSet) it.next();
309: fs.setDefaultIncludes();
310: DirectoryScanner scanner = fs
311: .getDirectoryScanner(project);
312: config.addFile(scanner.getBasedir(), scanner
313: .getIncludedFiles());
314: }
315:
316: /**
317: * For command-line interface
318: */
319: it = srcFiles.iterator();
320: while (it.hasNext()) {
321: config.addFile((File) it.next());
322: }
323:
324: config.setName(title);
325:
326: if (revisionMapper != null) {
327: config
328: .setRevisionMapper((RevisionMapper) revisionMapper
329: .getObject(null));
330: }
331:
332: ConnectionPerThreadDataSource dataSource = createDataSource(reviewSession);
333:
334: reviewSession.setDatasource(dataSource);
335:
336: final LinkedList repoWarnings = new LinkedList();
337: config.setWarningSink(new WarningSink() {
338: public void consume(final String source,
339: final String message) {
340: repoWarnings.add(new Violation() {
341: public String getMessage() {
342: return message;
343: }
344:
345: public InspectorDescriptor getDescriptor() {
346: return null;
347: }
348:
349: SourceMarker sm = new SimpleSourceMarker(0, 0,
350: source, null);
351:
352: public SourceMarker getSource() {
353: return sm;
354: }
355:
356: public int compareTo(Object obj) {
357: if (obj instanceof Violation) {
358: Violation v = (Violation) obj;
359: int c = SourceMarkerComparator
360: ._compare(getSource(), v
361: .getSource());
362: return c == 0 ? getMessage().compareTo(
363: v.getMessage()) : c;
364: }
365:
366: return hashCode() - obj.hashCode();
367: }
368: });
369: }
370: });
371:
372: config.setDataSource(dataSource);
373: final SQLProcessor sqlProcessor = new SQLProcessor(
374: dataSource, null);
375: sqlProcessor.setTimeIntervalCategory(tic);
376:
377: DbRepositoryImpl repositoryImpl = new DbRepositoryImpl(
378: config);
379: Repository repository = wrap ? (Repository) repositoryImpl
380: .getProxy() : repositoryImpl;
381:
382: //new SimpleResultsFactory(waiverSet).install();
383:
384: ResultsFactoryConfig rfConfig = new ResultsFactoryConfig();
385: rfConfig.setInspectorSet(inspectorSet);
386: rfConfig.setName(title);
387: rfConfig.setReportNumber(repository.getScanNumber());
388: rfConfig.setRepository(repository);
389: rfConfig.setSqlProcessor(sqlProcessor);
390: rfConfig.setHostId(hostId);
391: rfConfig.setBaseLine(baseLine);
392: rfConfig.setDescription(reviewDescription);
393:
394: try {
395: rfConfig.setHostName(InetAddress.getLocalHost()
396: .getHostName());
397: } catch (Exception e) {
398: log("Cannot resolve host name: " + e);
399: }
400:
401: CompositeStorage storage = new CompositeStorage();
402: storage.addStorage("jdbc", new JdbcStorage(sqlProcessor));
403: storage.addStorage("file", new FileStorage(new File(System
404: .getProperties().getProperty("java.io.tmpdir"))));
405: storage.addStorage("memory", new MemoryStorage());
406:
407: rfConfig.setStorage(storage);
408: rfConfig.setWaiverSet(waiverSet);
409:
410: ResultsFactory resultsFactory = new ResultsFactory(rfConfig);
411: resultsFactory.install();
412:
413: CompositeResults summary = org.hammurapi.results.ResultsFactory
414: .getInstance().newCompositeResults(title);
415: org.hammurapi.results.ResultsFactory.getInstance()
416: .setSummary(summary);
417: org.hammurapi.results.ResultsFactory
418: .pushThreadResults(summary);
419:
420: Collection inspectorsPerSe = new LinkedList(inspectorSet
421: .getInspectors());
422: reviewSession.setInspectors(inspectorSet);
423: Iterator inspectorsIt = inspectorsPerSe.iterator();
424: log("Inspectors mapping", Project.MSG_VERBOSE);
425: while (inspectorsIt.hasNext()) {
426: Inspector inspector = (Inspector) inspectorsIt.next();
427: log("\t"
428: + inspector.getContext().getDescriptor()
429: .getName() + " -> "
430: + inspector.getClass().getName(),
431: Project.MSG_VERBOSE);
432: }
433:
434: // Initializes listeners
435: it = listeners.iterator();
436: while (it.hasNext()) {
437: ((Listener) it.next()).onBegin(inspectorSet);
438: }
439:
440: Iterator vfit = violationFilters.iterator();
441: while (vfit.hasNext()) {
442: Object vf = vfit.next();
443: if (vf instanceof DataAccessObject) {
444: ((DataAccessObject) vf)
445: .setSQLProcessor(sqlProcessor);
446: }
447: }
448:
449: ResultsCollector collector = new ResultsCollector(this ,
450: inspectorSet, waiverSet, summary, listeners);
451: inspectorsPerSe.add(collector);
452:
453: // Storing repo warnings
454: while (!repoWarnings.isEmpty()) {
455: collector.getSummary().addWarning(
456: (Violation) repoWarnings.removeFirst());
457: }
458:
459: log("Reviewing", Project.MSG_VERBOSE);
460:
461: inspectorsPerSe.add(new ViolationFilterVisitor());
462:
463: SimpleReviewEngine rengine = new SimpleReviewEngine(
464: inspectorsPerSe, this );
465: reviewSession.setVisitor(rengine.getVisitor());
466: visitorStack[0] = rengine.getVisitorStack();
467:
468: rengine.review(repository);
469:
470: writeWaiverStubs(waiverSet.getRejectedRequests());
471:
472: ResultsFactory.getInstance().commit(
473: System.currentTimeMillis() - started);
474:
475: if (cleanup) {
476: repositoryImpl.cleanupOldScans();
477: resultsFactory.cleanupOldReports();
478: }
479:
480: repositoryImpl.stop();
481: reviewSession.shutdown();
482: resultsFactory.shutdown();
483: dataSource.shutdown();
484:
485: //log("SQL metrics:\n"+resultsFactory.getSQLMetrics(),Project.MSG_VERBOSE);
486:
487: if (hadExceptions) {
488: throw new BuildException(
489: "There have been exceptions during execution. Check log output.");
490: }
491: } catch (JselException e) {
492: throw new BuildException(e);
493: } catch (HammurapiException e) {
494: throw new BuildException(e);
495: } catch (ConfigurationException e) {
496: throw new BuildException(e);
497: } catch (FileNotFoundException e) {
498: throw new BuildException(e);
499: } catch (ClassNotFoundException e) {
500: throw new BuildException(e);
501: } catch (IOException e) {
502: throw new BuildException(e);
503: } catch (SQLException e) {
504: throw new BuildException(e);
505: } catch (RenderingException e) {
506: throw new BuildException(e);
507: } finally {
508: if (archiveTmpDir != null) {
509: deleteFile(archiveTmpDir);
510: }
511: }
512: }
513:
514: /**
515: * @param reviewSession
516: * @param hammurapiNameMap
517: * @param dataSource
518: * @param hammurapiNameMap
519: * @return
520: * @throws ClassNotFoundException
521: * @throws IOException
522: * @throws SQLException
523: */
524: private ConnectionPerThreadDataSource createDataSource(
525: final SessionImpl reviewSession)
526: throws ClassNotFoundException, IOException, SQLException {
527: ConnectionPerThreadDataSource dataSource;
528: if (database == null && server == null && connection == null) {
529: dataSource = new HypersonicTmpDataSource(
530: DbRepositoryImpl.HYPERSONIC_INIT_SCRIPT);
531: SQLProcessor sqlProcessor = new SQLProcessor(dataSource,
532: null);
533: sqlProcessor.setTimeIntervalCategory(tic);
534: sqlProcessor.executeScript(new InputStreamReader(getClass()
535: .getClassLoader().getResourceAsStream(
536: ResultsFactory.HYPERSONIC_INIT_SCRIPT)));
537:
538: reviewSession.scheduleInitDb();
539: } else if (database != null && server == null
540: && connection == null) {
541: reviewSession.setDbProperty("type", "Hypersonic");
542:
543: dataSource = new HypersonicStandaloneDataSource(database
544: .getAbsolutePath(), new Transaction() {
545:
546: public boolean execute(SQLProcessor processor)
547: throws SQLException {
548: processor.setTimeIntervalCategory(tic);
549: try {
550: processor
551: .executeScript(new InputStreamReader(
552: getClass()
553: .getClassLoader()
554: .getResourceAsStream(
555: DbRepositoryImpl.HYPERSONIC_INIT_SCRIPT)));
556: processor
557: .executeScript(new InputStreamReader(
558: getClass()
559: .getClassLoader()
560: .getResourceAsStream(
561: ResultsFactory.HYPERSONIC_INIT_SCRIPT)));
562: } catch (IOException e) {
563: throw new BuildException(
564: "Cannot initialize database", e);
565: }
566:
567: reviewSession.scheduleInitDb();
568: return true;
569: }
570: });
571: } else if (database == null && server != null
572: && connection == null) {
573: dataSource = new HypersonicServerDataSource(server
574: .getHost(), server.getUser(), server.getPassword(),
575: null);
576: } else if (database == null && server == null
577: && connection != null) {
578: dataSource = connection.getDataSource();
579: } else {
580: throw new BuildException(
581: "server nested element, connection nested element and database attribute are mutually exclusive");
582: }
583: return dataSource;
584: }
585:
586: /**
587: * Host id to differentiate reports created on different machines.
588: * @ant.non-required
589: */
590: public void setHostId(String hostId) {
591: this .hostId = hostId;
592: }
593:
594: private ServerEntry server;
595:
596: private ConnectionEntry connection;
597:
598: private boolean calculateDependencies;
599: private boolean storeSource;
600:
601: /**
602: * Use it for inspector debugging
603: * @param args
604: */
605: public static void main(String[] args) {
606: System.out
607: .println("Hammurapi 3 Copyright (C) 2004 Hammurapi Group");
608:
609: Options options = new Options();
610:
611: populateOptions(options);
612:
613: CommandLineParser parser = new PosixParser();
614: CommandLine line = null;
615: try {
616: line = parser.parse(options, args);
617: } catch (ParseException e) {
618: System.err.println(e.getMessage());
619: System.err.flush();
620: printHelpAndExit(options);
621: }
622:
623: if (line.hasOption("h")) {
624: printHelpAndExit(options);
625: }
626:
627: HammurapiTask task = new HammurapiTask();
628: Project project = new Project();
629: task.setProject(project);
630: project.setCoreLoader(task.getClass().getClassLoader());
631:
632: task.configure(options, line);
633:
634: task.suppressLogo = true;
635:
636: task.setTaskName("hammurapi");
637:
638: try {
639: task.execute();
640: System.exit(0);
641: } catch (Exception e) {
642: e.printStackTrace();
643: System.exit(2);
644: }
645: }
646:
647: /**
648: * @param options
649: * @param line
650: * @param task
651: * @param project
652: */
653: protected void configure(Options options, CommandLine line) {
654: super .configure(options, line);
655:
656: if (line.hasOption('z')) {
657: setCalculateDependencies(true);
658: }
659:
660: if (line.hasOption('b')) {
661: setStoreSource(true);
662: }
663:
664: if (line.hasOption('n')) {
665: setBaseLine(new Date(line.getOptionValue('n')));
666: }
667:
668: //if (line.hasOption('B')) {
669: // setBaselining(line.getOptionValue('B'));
670: //}
671:
672: if (line.hasOption('H')) {
673: setHostId(line.getOptionValue('H'));
674: }
675:
676: if (line.hasOption('L')) {
677: ConnectionEntry ce = new ConnectionEntry();
678: ce.setDriverClass(line.getOptionValue('L'));
679: ce.setUrl(line.getOptionValue('N'));
680: ce.setUser(line.getOptionValue('j'));
681: ce.setPassword(line.getOptionValue('p'));
682: addConnection(ce);
683: }
684:
685: if (line.hasOption('R')) {
686: addServer(new ServerEntry(line.getOptionValue('R'), line
687: .getOptionValue('j'), line.getOptionValue('p')));
688: }
689:
690: if (line.hasOption('F')) {
691: setForceOnWaivers(false);
692: }
693:
694: //setWrap(line.hasOption('r'));
695: }
696:
697: //Anu 20050701 : Method moved to TaskBase.java
698: // /**
699: // * Sets baselining mode. Possible values:
700: // * off (default) - no baselining, on - do not report
701: // * violations stored in the baseline table, set - all violations
702: // * from current scan are saved to the baseline table.
703: // * The idea is to filter out all violations in
704: // * preexisting code and report only new violations.
705: // * Not all violations can be filtered out, only thouse
706: // * with signatures. Significant code modifications can surface some
707: // * baselined violation.
708: // * @ant.non-required
709: // * @param baselineMode
710: // */
711: // public void setBaselining(String baselineMode) {
712: // if ("off".equals(baselineMode)) {
713: // // Nothing.
714: // } else if ("on".equals(baselineMode)) {
715: // violationFilters.add(new BaselineViolationFilter());
716: // } else if ("set".equalsIgnoreCase(baselineMode)) {
717: // violationFilters.add(new BaselineSetupViolationFilter());
718: // } else {
719: // throw new BuildException("Invalid baselining mode: "+baselineMode);
720: // }
721: //
722: // }
723:
724: /**
725: * @param options
726: */
727: protected static void populateOptions(Options options) {
728: TaskBase.populateOptions(options);
729:
730: Option hostIdOption = OptionBuilder.withArgName("hostId")
731: .hasArg().withDescription("Host id").isRequired(false)
732: .create("H");
733:
734: options.addOption(hostIdOption);
735:
736: //Anu 20050701 : Moved to TaskBase.java
737: // Option baseliningOption=OptionBuilder
738: // .withArgName("off|on|set")
739: // .hasArg()
740: // .withDescription("Baselining mode")
741: // .isRequired(false)
742: // .create("B");
743:
744: // options.addOption(baseliningOption);
745:
746: Option serverOption = OptionBuilder.withDescription(
747: "Database server name").withArgName("database server")
748: .hasArg().isRequired(false).create("R");
749:
750: options.addOption(serverOption);
751:
752: Option driverClassOption = OptionBuilder.withDescription(
753: "Database driver class").withArgName("class name")
754: .hasArg().isRequired(false).create("L");
755:
756: options.addOption(driverClassOption);
757:
758: Option connectionUrlOption = OptionBuilder.withDescription(
759: "Database connection URL").withArgName("url").hasArg()
760: .isRequired(false).create("N");
761:
762: options.addOption(connectionUrlOption);
763:
764: Option userOption = OptionBuilder.withDescription(
765: "Database user").withArgName("user name").hasArg()
766: .isRequired(false).create("j");
767:
768: options.addOption(userOption);
769:
770: Option passwordOption = OptionBuilder.withDescription(
771: "Database password").withArgName("password").hasArg()
772: .isRequired(false).create("p");
773:
774: options.addOption(passwordOption);
775:
776: Option baseLineOption = OptionBuilder.withDescription(
777: "Baseline date").withArgName("date").hasArg()
778: .isRequired(false).create("n");
779:
780: options.addOption(baseLineOption);
781:
782: Option calculateDependenciesOption = OptionBuilder
783: .withDescription("Calculate dependencies").isRequired(
784: false).create("z");
785:
786: options.addOption(calculateDependenciesOption);
787:
788: Option storeSourceOption = OptionBuilder.withDescription(
789: "Store source").isRequired(false).create("b");
790:
791: options.addOption(storeSourceOption);
792:
793: Option forceOnWaiversOption = OptionBuilder.withDescription(
794: "Do not force reviews on waivers").isRequired(false)
795: .create("F");
796:
797: options.addOption(forceOnWaiversOption);
798:
799: }
800:
801: /**
802: * If set to 'true' Hammurapi stores dependency information to the
803: * database.
804: * @ant.non-required
805: * @param b
806: */
807: public void setCalculateDependencies(boolean calculateDependencies) {
808: this .calculateDependencies = calculateDependencies;
809: }
810:
811: /**
812: * If set to 'true' Hammurapi stores source code to the database.
813: * @ant.non-required
814: * @param b
815: */
816: public void setStoreSource(boolean storeSource) {
817: this .storeSource = storeSource;
818: }
819:
820: /**
821: * Database (Hypersonic) server to use as repository.
822: * @param entry
823: * @ant.non-required
824: */
825: public void addServer(ServerEntry server) {
826: this .server = server;
827: }
828:
829: /**
830: * Defines database server to be used as repository.
831: * Mutually exclusive with server nested element and database attribute.
832: * @ant.non-required.
833: * @param connection
834: */
835: public void addConnection(ConnectionEntry connection) {
836: this .connection = connection;
837: }
838:
839: /**
840: * @param config
841: * @throws ParseException
842: */
843: protected void setAttributes(Element config) {
844: super .setAttributes(config);
845: if (config.hasAttribute("host-id")) {
846: setHostId(config.getAttribute("host-id"));
847: }
848: if (config.hasAttribute("baseline")) {
849: try {
850: setBaseLine(new SimpleDateFormat(
851: HammurapiArchiver.DATE_FORMAT).parse(config
852: .getAttribute("baseline")));
853: } catch (java.text.ParseException e) {
854: throw new BuildException("Cannot parse baseline date",
855: e);
856: }
857: }
858: }
859: }
|