0001: /*
0002: * Hammurapi
0003: * Automated Java code review system.
0004: * Copyright (C) 2004 Hammurapi Group
0005: *
0006: * This program is free software; you can redistribute it and/or modify
0007: * it under the terms of the GNU General Public License as published by
0008: * the Free Software Foundation; either version 2 of the License, or
0009: * (at your option) any later version.
0010: *
0011: * This program is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0014: * GNU General Public License for more details.
0015: *
0016: * You should have received a copy of the GNU General Public License
0017: * along with this program; if not, write to the Free Software
0018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0019: *
0020: * URL: http://www.hammurapi.org
0021: * e-Mail: support@hammurapi.biz
0022: */
0023: package org.hammurapi;
0024:
0025: import java.io.File;
0026: import java.io.FileNotFoundException;
0027: import java.io.FileOutputStream;
0028: import java.io.IOException;
0029: import java.io.InputStream;
0030: import java.io.PrintStream;
0031: import java.text.ParseException;
0032: import java.text.SimpleDateFormat;
0033: import java.util.ArrayList;
0034: import java.util.Collection;
0035: import java.util.Date;
0036: import java.util.Enumeration;
0037: import java.util.HashSet;
0038: import java.util.Iterator;
0039: import java.util.LinkedList;
0040: import java.util.List;
0041: import java.util.zip.ZipEntry;
0042: import java.util.zip.ZipException;
0043: import java.util.zip.ZipFile;
0044:
0045: import javax.xml.parsers.DocumentBuilderFactory;
0046: import javax.xml.parsers.FactoryConfigurationError;
0047: import javax.xml.parsers.ParserConfigurationException;
0048: import javax.xml.transform.TransformerException;
0049:
0050: import org.apache.commons.cli.CommandLine;
0051: import org.apache.commons.cli.HelpFormatter;
0052: import org.apache.commons.cli.Option;
0053: import org.apache.commons.cli.OptionBuilder;
0054: import org.apache.commons.cli.Options;
0055: import org.apache.tools.ant.BuildException;
0056: import org.apache.tools.ant.BuildLogger;
0057: import org.apache.tools.ant.DefaultLogger;
0058: import org.apache.tools.ant.DemuxOutputStream;
0059: import org.apache.tools.ant.Project;
0060: import org.apache.tools.ant.Task;
0061: import org.apache.tools.ant.types.FileSet;
0062: import org.apache.tools.ant.types.Path;
0063: import org.apache.xpath.CachedXPathAPI;
0064: import org.hammurapi.render.dom.DetailedResultsRenderer;
0065: import org.hammurapi.results.persistent.jdbc.BaselineSetupViolationFilter;
0066: import org.hammurapi.results.persistent.jdbc.BaselineViolationFilter;
0067: import org.w3c.dom.Document;
0068: import org.w3c.dom.Element;
0069: import org.w3c.dom.traversal.NodeIterator;
0070: import org.xml.sax.SAXException;
0071:
0072: import com.pavelvlasov.ant.ObjectEntry;
0073: import com.pavelvlasov.ant.XmlSourceEntry;
0074: import com.pavelvlasov.jsel.RevisionMapper;
0075: import com.pavelvlasov.render.RenderRequest;
0076: import com.pavelvlasov.render.RenderingException;
0077: import com.pavelvlasov.render.dom.AbstractRenderer;
0078: import com.pavelvlasov.review.Signed;
0079: import com.pavelvlasov.util.ClassResourceLoader;
0080: import com.pavelvlasov.xml.dom.AbstractDomObject;
0081:
0082: /**
0083: * @author Pavel Vlasov
0084: *
0085: * @version $Revision: 1.9 $
0086: */
0087: public class TaskBase extends Task {
0088:
0089: protected void deleteFile(File file) {
0090: if (file != null) {
0091: if (file.isDirectory()) {
0092: File[] children = file.listFiles();
0093: if (children != null) {
0094: for (int i = 0; i < children.length; i++) {
0095: deleteFile(children[i]);
0096: }
0097: }
0098: }
0099:
0100: if (file.isFile() || file.isDirectory()) {
0101: file.delete();
0102: }
0103: }
0104: }
0105:
0106: /**
0107: * @return Returns the reviewAcceptorEntries.
0108: */
0109: protected List getReviewAcceptorEntries() {
0110: return reviewAcceptorEntries;
0111: }
0112:
0113: /**
0114: * @return Returns the severityThreshold.
0115: */
0116: protected Integer getSeverityThreshold() {
0117: return severityThreshold;
0118: }
0119:
0120: /**
0121: * @return Returns the dpmoThreshold.
0122: */
0123: protected Double getSigmaThreshold() {
0124: return sigmaThreshold;
0125: }
0126:
0127: /**
0128: * @return Returns the dpmoThreshold.
0129: */
0130: protected Integer getDpmoThreshold() {
0131: return dpmoThreshold;
0132: }
0133:
0134: /**
0135: * @return Returns the failOnWarnings.
0136: */
0137: protected boolean isFailOnWarnings() {
0138: return failOnWarnings;
0139: }
0140:
0141: private File unpackDir;
0142:
0143: /**
0144: * If this attribute is set then HAR archive will be unpacked
0145: * in the given directory instead of a temporary one.
0146: * @ant.non-required
0147: * @param unpackDir
0148: */
0149: public void setUnpackDir(File unpackDir) {
0150: this .unpackDir = unpackDir;
0151: }
0152:
0153: /**
0154: * @return Returns the debugType.
0155: * @ant.ignore
0156: */
0157: public String getDebugType() {
0158: return debugType;
0159: }
0160:
0161: protected Collection srcFiles = new LinkedList();
0162:
0163: protected static void loadEmbeddedInspectors(
0164: InspectorSet inspectorSet) throws BuildException,
0165: HammurapiException {
0166: ClassResourceLoader crl = new ClassResourceLoader(
0167: TaskBase.class);
0168: InputStream inspectorStream = crl.getResourceAsStream(null,
0169: null, "xml");
0170: if (inspectorStream == null) {
0171: throw new BuildException("Cannot load embedded inspectors");
0172: }
0173:
0174: DomInspectorSource source = new DomInspectorSource(
0175: inspectorStream, "Hammurapi.jar");
0176: source.loadInspectors(inspectorSet);
0177: }
0178:
0179: /**
0180: * @param options
0181: */
0182: protected static void populateOptions(Options options) {
0183: Option waiverStubsOption = OptionBuilder.withArgName(
0184: "waiverStubs").hasArg().withDescription(
0185: "Where to output waiver stubs").isRequired(false)
0186: .create("w");
0187:
0188: options.addOption(waiverStubsOption);
0189:
0190: Option databaseOption = OptionBuilder.withDescription(
0191: "Database name").withArgName("local database").hasArg()
0192: .isRequired(false).create("D");
0193:
0194: options.addOption(databaseOption);
0195:
0196: Option includeInspectorOption = OptionBuilder.withDescription(
0197: "Enable inspector").withArgName("inspector name")
0198: .hasArg().isRequired(false).create("I");
0199:
0200: options.addOption(includeInspectorOption);
0201:
0202: Option configFileOption = OptionBuilder.withDescription(
0203: "Config file").withArgName("file").hasArg().isRequired(
0204: false).create("m");
0205:
0206: options.addOption(configFileOption);
0207:
0208: Option configUrlOption = OptionBuilder.withDescription(
0209: "Config url").withArgName("url").hasArg().isRequired(
0210: false).create("q");
0211:
0212: options.addOption(configUrlOption);
0213:
0214: Option unpackDirOption = OptionBuilder.withDescription(
0215: "Unpack directory").withArgName("directory").hasArg()
0216: .isRequired(false).create("r");
0217:
0218: options.addOption(unpackDirOption);
0219:
0220: Option excludeInspectorOption = OptionBuilder.withDescription(
0221: "Disable inspector").withArgName("inspector name")
0222: .hasArg().isRequired(false).create("X");
0223:
0224: options.addOption(excludeInspectorOption);
0225:
0226: Option archiveFileOption = OptionBuilder.withArgName("archive")
0227: .hasArg().withDescription("Hammurapi archive")
0228: .isRequired(false).create("A");
0229:
0230: options.addOption(archiveFileOption);
0231: Option waiversFileOption = OptionBuilder.withArgName(
0232: "waivers file").hasArg()
0233: .withDescription("Waivers File").isRequired(false)
0234: .create("W");
0235:
0236: options.addOption(waiversFileOption);
0237:
0238: Option forceOption = OptionBuilder.withDescription(
0239: "Force reviews of unchanged files").isRequired(false)
0240: .create("f");
0241:
0242: //Anu 20050701 : Baselining.Moved from HammurapiTask.java
0243: Option baseliningOption = OptionBuilder.withArgName(
0244: "off|on|set").hasArg().withDescription(
0245: "Baselining mode").isRequired(false).create("B");
0246:
0247: options.addOption(forceOption);
0248:
0249: Option forceOnWarningsOption = OptionBuilder.withDescription(
0250: "Do not force reviews of files with warnings")
0251: .isRequired(false).create("k");
0252:
0253: options.addOption(forceOnWarningsOption);
0254:
0255: Option doNotEvictOption = OptionBuilder.withDescription(
0256: "Evict bad inspectors").isRequired(false).create("E");
0257:
0258: options.addOption(doNotEvictOption);
0259:
0260: Option waiversUrlOption = OptionBuilder.withArgName(
0261: "waivers url").hasArg().withDescription("Waivers URL")
0262: .isRequired(false).create("U");
0263:
0264: options.addOption(waiversUrlOption);
0265:
0266: Option classPathOption = OptionBuilder.withArgName("classpath")
0267: .hasArg().withDescription("ClassPath")
0268: .isRequired(false).create("c");
0269:
0270: options.addOption(classPathOption);
0271:
0272: Option sigmaThresholdOption = OptionBuilder.withArgName(
0273: "sigmaThreshold").hasArg().withDescription(
0274: "Sigma threshold").isRequired(false).create("s");
0275:
0276: options.addOption(sigmaThresholdOption);
0277:
0278: Option dpmoThresholdOption = OptionBuilder.withArgName(
0279: "dpmoThreshold").hasArg().withDescription(
0280: "DPMO Threshold").isRequired(false).create("d");
0281:
0282: options.addOption(dpmoThresholdOption);
0283:
0284: Option severityThresholdOption = OptionBuilder.withArgName(
0285: "severityThreshold").hasArg().withDescription(
0286: "Severity threshold").isRequired(false).create("S");
0287:
0288: options.addOption(severityThresholdOption);
0289:
0290: Option noEmbeddedInspectorsOption = OptionBuilder
0291: .withDescription("Do not load embedded inspectors")
0292: .isRequired(false).create("e");
0293:
0294: options.addOption(noEmbeddedInspectorsOption);
0295:
0296: Option inspectorsFileOption = OptionBuilder.withArgName(
0297: "inspectorsFile").hasArg().withDescription(
0298: "Inspectors file").isRequired(false).create("i");
0299:
0300: options.addOption(inspectorsFileOption);
0301:
0302: Option inspectorsURLOption = OptionBuilder.withArgName(
0303: "inspectorsURL").hasArg().withDescription(
0304: "Inspectors URL").isRequired(false).create("u");
0305:
0306: options.addOption(inspectorsURLOption);
0307:
0308: Option titleOption = OptionBuilder.withArgName("title")
0309: .hasArg().withDescription("Report title").isRequired(
0310: false).create("T");
0311:
0312: options.addOption(titleOption);
0313:
0314: Option debugTypeOption = OptionBuilder
0315: .withArgName("debug type").hasArg().withDescription(
0316: "Jsel type to debug").isRequired(false).create(
0317: "t");
0318:
0319: options.addOption(debugTypeOption);
0320:
0321: Option listenerOption = OptionBuilder.withArgName("class name")
0322: .hasArg().withDescription("Review listener")
0323: .isRequired(false).create("l");
0324:
0325: options.addOption(listenerOption);
0326:
0327: Option debugOption = OptionBuilder.withDescription("Debug")
0328: .isRequired(false).create("g");
0329:
0330: options.addOption(debugOption);
0331:
0332: Option verboseOption = OptionBuilder.withDescription("Verbose")
0333: .isRequired(false).create("v");
0334:
0335: options.addOption(verboseOption);
0336:
0337: Option xmlOption = OptionBuilder.withDescription("Output XML")
0338: .isRequired(false).create("x");
0339:
0340: options.addOption(xmlOption);
0341:
0342: Option suppressOutputOption = OptionBuilder.withDescription(
0343: "Suppress output").isRequired(false).create("o");
0344:
0345: options.addOption(suppressOutputOption);
0346:
0347: Option descriptionOption = OptionBuilder.withDescription(
0348: "Review description").withArgName("description")
0349: .hasArg().isRequired(false).create("y");
0350:
0351: options.addOption(descriptionOption);
0352:
0353: Option helpOption = OptionBuilder.withDescription(
0354: "Print this message").isRequired(false).create("h");
0355: options.addOption(helpOption);
0356: }
0357:
0358: protected static void printHelpAndExit(Options options) {
0359: HelpFormatter formatter = new HelpFormatter();
0360: formatter
0361: .printHelp(
0362: "Usage: hammurapi [options] <output dir> <source files/dirs>",
0363: options, false);
0364: System.exit(1);
0365: }
0366:
0367: /**
0368: * Class name to debug
0369: * @ant.non-required
0370: */
0371: public void setDebugType(String debugType) {
0372: this .debugType = debugType;
0373: }
0374:
0375: /**
0376: * Load embedded inspectors. Defaults to true.
0377: * @ant.non-required
0378: */
0379: public void setEmbeddedInspectors(boolean embeddedInspectors) {
0380: this .embeddedInspectors = embeddedInspectors;
0381: }
0382:
0383: private String debugType;
0384: protected boolean embeddedInspectors = true;
0385: protected List srcFileSets = new LinkedList();
0386:
0387: /**
0388: * Source files fileset.
0389: * @ant.non-required
0390: */
0391: public FileSet createSrc() {
0392: FileSet ret = new HammurapiFileSet("**/*.java");
0393: srcFileSets.add(ret);
0394: return ret;
0395: }
0396:
0397: protected void setHadExceptions() {
0398: hadExceptions = true;
0399: }
0400:
0401: /**
0402: * @param collection
0403: * @throws FileNotFoundException
0404: * @throws RenderingException
0405: */
0406: protected void writeWaiverStubs(final Collection rejectedViolations)
0407: throws RenderingException, FileNotFoundException {
0408: if (waiverStubs != null) {
0409: class WaiverStubsRenderer extends AbstractRenderer {
0410: WaiverStubsRenderer() {
0411: super (new RenderRequest(rejectedViolations));
0412: }
0413:
0414: public Element render(Document document) {
0415: Element ret = document.createElement("waivers");
0416: Iterator it = rejectedViolations.iterator();
0417: final Date now = new Date();
0418: while (it.hasNext()) {
0419: final Violation violation = (Violation) it
0420: .next();
0421:
0422: StringBuffer comment = new StringBuffer();
0423: comment.append("Source: ");
0424: comment.append(violation.getSource()
0425: .getSourceURL());
0426:
0427: comment.append("\nLine: ");
0428: comment.append(violation.getSource().getLine());
0429:
0430: comment.append("\nCol: ");
0431: comment.append(violation.getSource()
0432: .getColumn());
0433:
0434: comment.append("\nDescription: ");
0435: comment.append(violation.getDescriptor()
0436: .getDescription());
0437:
0438: comment.append("\nMesssage: ");
0439: comment.append(violation.getMessage());
0440:
0441: ret.appendChild(document.createComment(comment
0442: .toString()));
0443:
0444: Waiver waiver = new Waiver() {
0445:
0446: public String getInspectorName() {
0447: return violation.getDescriptor()
0448: .getName();
0449: }
0450:
0451: public Date getExpirationDate() {
0452: return now;
0453: }
0454:
0455: public String getReason() {
0456: return "*** Put reason here ***";
0457: }
0458:
0459: public boolean waive(Violation violation,
0460: boolean peek) {
0461: // This 'waiver' will never waive anything, it is used only for rendering
0462: return false;
0463: }
0464:
0465: public boolean isActive() {
0466: // This 'waiver' will never waive anything, it is used only for rendering
0467: return false;
0468: }
0469:
0470: Collection signatures = new HashSet();
0471:
0472: {
0473: if (violation.getSource() instanceof Signed) {
0474: signatures.add(((Signed) violation
0475: .getSource())
0476: .getSignature());
0477: }
0478: }
0479:
0480: public Collection getSignatures() {
0481: return signatures;
0482: }
0483: };
0484: ret.appendChild(DetailedResultsRenderer
0485: .renderWaiver(waiver, document));
0486: }
0487: return ret;
0488: }
0489: }
0490: WaiverStubsRenderer renderer = new WaiverStubsRenderer();
0491: renderer.setEmbeddedStyle(false);
0492: renderer.render(new FileOutputStream(waiverStubs));
0493: }
0494: }
0495:
0496: protected File processArchive() {
0497: if (archive == null) {
0498: return null;
0499: }
0500:
0501: String tmpDirProperty = System.getProperty("java.io.tmpdir");
0502: File tmpDir = tmpDirProperty == null ? new File(".")
0503: : new File(tmpDirProperty);
0504: SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
0505: String prefix = "har_" + sdf.format(new Date());
0506: File workDir = unpackDir == null ? new File(tmpDir, prefix)
0507: : unpackDir;
0508:
0509: for (int i = 0; unpackDir == null && workDir.exists(); i++) {
0510: workDir = new File(tmpDir, prefix + "_"
0511: + Integer.toString(i, Character.MAX_RADIX));
0512: }
0513:
0514: if (workDir.exists() || workDir.mkdir()) {
0515: try {
0516: ZipFile zipFile = new ZipFile(archive);
0517: Enumeration entries = zipFile.entries();
0518: while (entries.hasMoreElements()) {
0519: ZipEntry entry = (ZipEntry) entries.nextElement();
0520: if (!entry.getName().endsWith("/")) {
0521: File outFile = new File(workDir, entry
0522: .getName().replace('/',
0523: File.separatorChar));
0524: if (!outFile.getParentFile().exists()
0525: && !outFile.getParentFile().mkdirs()) {
0526: throw new BuildException(
0527: "Directory does not exist and cannot be created: "
0528: + outFile.getParentFile()
0529: .getAbsolutePath());
0530: }
0531:
0532: log("Archive entry " + entry.getName()
0533: + " unpacked to "
0534: + outFile.getAbsolutePath(),
0535: Project.MSG_DEBUG);
0536:
0537: byte[] buf = new byte[4096];
0538: int l;
0539: InputStream in = zipFile.getInputStream(entry);
0540: FileOutputStream fos = new FileOutputStream(
0541: outFile);
0542: while ((l = in.read(buf)) != -1) {
0543: fos.write(buf, 0, l);
0544: }
0545: in.close();
0546: fos.close();
0547: }
0548: }
0549: zipFile.close();
0550:
0551: File configFile = new File(workDir, "config.xml");
0552: if (configFile.exists() && configFile.isFile()) {
0553: Document configDoc = DocumentBuilderFactory
0554: .newInstance().newDocumentBuilder().parse(
0555: configFile);
0556: processConfig(workDir, configDoc
0557: .getDocumentElement());
0558: } else {
0559: throw new BuildException(
0560: "Archive configuration file does not exist or is not a file");
0561: }
0562: } catch (ZipException e) {
0563: throw new BuildException(e.toString(), e);
0564: } catch (IOException e) {
0565: throw new BuildException(e.toString(), e);
0566: } catch (SAXException e) {
0567: throw new BuildException(e.toString(), e);
0568: } catch (ParserConfigurationException e) {
0569: throw new BuildException(e.toString(), e);
0570: } catch (FactoryConfigurationError e) {
0571: throw new BuildException(e.toString(), e);
0572: }
0573: } else {
0574: throw new BuildException("Could not create directory "
0575: + workDir.getAbsolutePath());
0576: }
0577: return unpackDir == null ? workDir : null;
0578: }
0579:
0580: /**
0581: * @param workDir
0582: * @param configDoc
0583: * @throws ParseException
0584: * @throws TransformerException
0585: */
0586: private void processConfig(File workDir, Element config) {
0587: if (config != null) {
0588: try {
0589: setAttributes(config);
0590:
0591: CachedXPathAPI cxpa = new CachedXPathAPI();
0592: NodeIterator nit = cxpa.selectNodeIterator(config,
0593: "sources/source");
0594: Element element;
0595: while ((element = (Element) nit.nextNode()) != null) {
0596: srcFiles.add(new File(workDir, AbstractDomObject
0597: .getElementText(element)));
0598: }
0599:
0600: nit = cxpa.selectNodeIterator(config, "classpath/path");
0601: while ((element = (Element) nit.nextNode()) != null) {
0602: File cpe = new File(workDir, AbstractDomObject
0603: .getElementText(element));
0604: if (cpe.exists()) {
0605: createClasspath().setLocation(cpe);
0606: log("File " + cpe.getAbsolutePath()
0607: + " added to classpath",
0608: Project.MSG_DEBUG);
0609: } else {
0610: throw new BuildException("Classpath element "
0611: + cpe.getAbsolutePath()
0612: + " does not exist");
0613: }
0614: }
0615: } catch (TransformerException e) {
0616: throw new BuildException("Cannot load config", e);
0617: }
0618: }
0619: }
0620:
0621: /**
0622: * @param config
0623: * @throws ParseException
0624: */
0625: protected void setAttributes(Element config) {
0626: if (config.hasAttribute("title")) {
0627: setTitle(config.getAttribute("title"));
0628: }
0629:
0630: if (config.hasAttribute("dpmo-threshold")) {
0631: setDpmoThreshold(Integer.parseInt(config
0632: .getAttribute("dpmo-threshold")));
0633: }
0634:
0635: if (config.hasAttribute("sigma-threshold")) {
0636: setSigmaThreshold(Double.parseDouble(config
0637: .getAttribute("sigma-threshold")));
0638: }
0639:
0640: if (config.hasAttribute("severity-threshold")) {
0641: setSeverityThreshold(Integer.parseInt(config
0642: .getAttribute("severity-threshold")));
0643: }
0644:
0645: if (config.hasAttribute("force")) {
0646: setForce("yes".equals(config.getAttribute("force")));
0647: }
0648:
0649: if (config.hasAttribute("force-on-warnings")) {
0650: setForceOnWarnings("yes".equals(config
0651: .getAttribute("force-on-warnings")));
0652: }
0653:
0654: if (config.hasAttribute("review-description")) {
0655: setReviewDescription(config
0656: .getAttribute("review-description"));
0657: }
0658:
0659: //Anu : 20050701 for baselining
0660: if (config.hasAttribute("baselining")) {
0661: setBaselining(config.getAttribute("baselining"));
0662: }
0663: }
0664:
0665: protected boolean suppressLogo;
0666:
0667: /**
0668: * Defines output
0669: * @ant.non-required
0670: */
0671: public Output createOutput() {
0672: Output output = new Output(this );
0673: outputs.add(output);
0674: return output;
0675: }
0676:
0677: /**
0678: * Defines history output, which stores review summary
0679: * into database.
0680: * @ant.non-required
0681: */
0682: public HistoryOutput createHistoryOutput() {
0683: HistoryOutput historyOutput = new HistoryOutput();
0684: outputs.add(historyOutput);
0685: return historyOutput;
0686: }
0687:
0688: protected List outputs = new LinkedList();
0689: protected boolean hadExceptions;
0690:
0691: /**
0692: * Maybe creates a nested classpath element.
0693: * @ant :non-required
0694: */
0695: public Path createClasspath() {
0696: if (classPath == null) {
0697: classPath = new Path(project);
0698: }
0699: return classPath.createPath();
0700: }
0701:
0702: public void setClassPath(Path classPath) {
0703: if (this .classPath == null) {
0704: this .classPath = classPath;
0705: } else {
0706: this .classPath.append(classPath);
0707: }
0708: }
0709:
0710: /**
0711: * Classpath for loading classes.
0712: * @ant :non-required
0713: */
0714: protected Path classPath;
0715:
0716: /**
0717: * Defines inspector
0718: * @ant.non-required
0719: */
0720: public InspectorEntry createInspector() {
0721: InspectorEntry inspectorEntry = new InspectorEntry();
0722: inspectors.add(inspectorEntry);
0723: return inspectorEntry;
0724: }
0725:
0726: protected List inspectors = new LinkedList();
0727:
0728: /**
0729: * Defines waivers source
0730: * @ant.non-required
0731: */
0732: public WaiverSourceEntry createWaivers() {
0733: WaiverSourceEntry ret = new WaiverSourceEntry();
0734: ret.setProject(getProject());
0735: waivers.add(ret);
0736: return ret;
0737: }
0738:
0739: private Collection configs = new ArrayList();
0740:
0741: protected void processConfigs(File baseDir) {
0742: Iterator it = configs.iterator();
0743: while (it.hasNext()) {
0744: XmlSourceEntry xse = (XmlSourceEntry) it.next();
0745: processConfig(xse.getFile() == null ? baseDir : xse
0746: .getFile(), xse.getDocumentElement());
0747: }
0748: }
0749:
0750: /**
0751: * Configuration source.
0752: * Task can be configured from multiple sources.
0753: * @ant.non-required
0754: */
0755: public XmlSourceEntry createConfig() {
0756: XmlSourceEntry ret = new XmlSourceEntry();
0757: configs.add(ret);
0758: ret.setProject(getProject());
0759: return ret;
0760: }
0761:
0762: /**
0763: * Defines inspector source
0764: * @ant.non-required
0765: */
0766: public InspectorSourceEntry createInspectors() {
0767: InspectorSourceEntry ret = new InspectorSourceEntry();
0768: inspectors.add(ret);
0769: ret.setProject(getProject());
0770: return ret;
0771: }
0772:
0773: /**
0774: * Hammurapi archive to process.
0775: * @ant.non-required
0776: * @param archive
0777: */
0778: public void setArchive(File archive) {
0779: this .archive = archive;
0780: }
0781:
0782: private File archive;
0783:
0784: /**
0785: * Fail build if project DPMO is above the threshold.
0786: * @ant.non-required
0787: */
0788: public void setDpmoThreshold(int dpmoThreshold)
0789: throws BuildException {
0790: this .dpmoThreshold = new Integer(dpmoThreshold);
0791: }
0792:
0793: /**
0794: * Fail build if project Sigma is below the threshold.
0795: * @ant.non-required
0796: */
0797: public void setSigmaThreshold(double sigmaThreshold)
0798: throws BuildException {
0799: this .sigmaThreshold = new Double(sigmaThreshold);
0800: }
0801:
0802: protected Collection waivers = new LinkedList();
0803: private Integer dpmoThreshold;
0804: private Double sigmaThreshold;
0805:
0806: /**
0807: * Review listener
0808: * @ant.non-required
0809: */
0810: public void addConfiguredListener(ListenerEntry listener) {
0811: listenerEntries.add(listener);
0812: }
0813:
0814: /**
0815: * Review acceptor.
0816: * @ant.non-required
0817: */
0818: public void addConfiguredReviewAcceptor(
0819: ReviewAcceptorEntry reviewAcceptor) throws BuildException {
0820: reviewAcceptorEntries.add(reviewAcceptor);
0821: }
0822:
0823: private List reviewAcceptorEntries = new LinkedList();
0824:
0825: /**
0826: * Fail build as soon as there is an exception. Default is false.
0827: * @ant.non-required
0828: */
0829: public void setFailOnFirstException(boolean failOnFirstException) {
0830: this .failOnFirstException = failOnFirstException;
0831: }
0832:
0833: protected boolean failOnFirstException = false;
0834:
0835: /**
0836: * Fail build if there have been warnings. Default is true.
0837: * @ant.non-required
0838: */
0839: public void setFailOnWarnings(boolean failOnWarnings) {
0840: this .failOnWarnings = failOnWarnings;
0841: }
0842:
0843: private boolean failOnWarnings = true;
0844:
0845: /**
0846: * Fail build on violations with severity levels lower or equal to the threshold.
0847: * @ant.non-required
0848: */
0849: public void setSeverityThreshold(int severityThreshold) {
0850: this .severityThreshold = new Integer(severityThreshold);
0851: }
0852:
0853: /**
0854: * @ant.non-required
0855: * @param title
0856: */
0857: public void setTitle(String title) {
0858: this .title = title;
0859: }
0860:
0861: protected String title = "Summary " + new Date();
0862:
0863: /**
0864: * @param options
0865: * @param line
0866: * @param task
0867: * @param project
0868: */
0869: protected void configure(Options options, CommandLine line) {
0870: String[] largs = line.getArgs();
0871: if (largs.length == 0) {
0872: System.out.println("Output dir has to be provided");
0873: printHelpAndExit(options);
0874: }
0875:
0876: if (!line.hasOption('o')) {
0877: new File(largs[0]).mkdirs();
0878: Output output = createOutput();
0879: output.setDir(largs[0]);
0880:
0881: if (line.hasOption('x')) {
0882: output.setEmbeddedStyle(false);
0883: output.setExtension(".xml");
0884: }
0885: }
0886:
0887: if (largs.length == 1 && !line.hasOption('A')) {
0888: System.out
0889: .println("At least one source directory or archive must be provided");
0890: printHelpAndExit(options);
0891: }
0892:
0893: if (line.hasOption('y')) {
0894: setReviewDescription(line.getOptionValue('y'));
0895: }
0896:
0897: for (int i = 1; i < largs.length; i++) {
0898: File file = new File(largs[i]);
0899: if (file.isFile()) {
0900: srcFiles.add(file);
0901: } else if (file.isDirectory()) {
0902: createSrc().setDir(file);
0903: }
0904: }
0905:
0906: String[] values = line.getOptionValues('c');
0907: for (int i = 0; values != null && i < values.length; i++) {
0908: createClasspath().append(new Path(project, values[i]));
0909: }
0910:
0911: values = line.getOptionValues('m');
0912: for (int i = 0; values != null && i < values.length; i++) {
0913: createConfig().setFile(new File(values[i]));
0914: }
0915:
0916: values = line.getOptionValues('q');
0917: for (int i = 0; values != null && i < values.length; i++) {
0918: createConfig().setURL(values[i]);
0919: }
0920:
0921: values = line.getOptionValues('I');
0922: for (int i = 0; values != null && i < values.length; i++) {
0923: InspectorEntry ie = createInspector();
0924: ie.setName(values[i]);
0925: ie.setEnabled(true);
0926: }
0927:
0928: values = line.getOptionValues('X');
0929: for (int i = 0; values != null && i < values.length; i++) {
0930: InspectorEntry ie = createInspector();
0931: ie.setName(values[i]);
0932: ie.setEnabled(false);
0933: }
0934:
0935: setEvictBadInspectors(line.hasOption('E'));
0936:
0937: setEmbeddedInspectors(!line.hasOption('e'));
0938:
0939: if (line.hasOption('t')) {
0940: setDebugType(line.getOptionValue('t'));
0941: }
0942:
0943: if (line.hasOption('r')) {
0944: setUnpackDir(new File(line.getOptionValue('r')));
0945: }
0946:
0947: if (line.hasOption('T')) {
0948: setTitle(line.getOptionValue('T'));
0949: }
0950:
0951: BuildLogger logger = new DefaultLogger();
0952: logger.setMessageOutputLevel(Project.MSG_INFO);
0953: logger.setOutputPrintStream(System.out);
0954: logger.setErrorPrintStream(System.err);
0955: logger.setEmacsMode(false);
0956:
0957: if (line.hasOption('v')) {
0958: logger.setMessageOutputLevel(Project.MSG_VERBOSE);
0959: }
0960:
0961: if (line.hasOption('g')) {
0962: logger.setMessageOutputLevel(Project.MSG_DEBUG);
0963: }
0964:
0965: project.addBuildListener(logger);
0966:
0967: System.setOut(new PrintStream(new DemuxOutputStream(project,
0968: false)));
0969: System.setErr(new PrintStream(new DemuxOutputStream(project,
0970: true)));
0971:
0972: if (line.hasOption('w')) {
0973: setWaiverStubs(new File(line.getOptionValue('w')));
0974: }
0975:
0976: if (line.hasOption('s')) {
0977: setSigmaThreshold(Double.parseDouble(line
0978: .getOptionValue('s')));
0979: }
0980:
0981: if (line.hasOption('d')) {
0982: setDpmoThreshold(Integer.parseInt(line.getOptionValue('d')));
0983: }
0984:
0985: if (line.hasOption('S')) {
0986: setSeverityThreshold(Integer.parseInt(line
0987: .getOptionValue('S')));
0988: }
0989:
0990: if (line.hasOption('f')) {
0991: setForce(true);
0992: }
0993:
0994: if (line.hasOption('k')) {
0995: setForceOnWarnings(false);
0996: }
0997:
0998: if (line.hasOption('D')) {
0999: setDatabase(new File(line.getOptionValue('D')));
1000: }
1001:
1002: values = line.getOptionValues('i');
1003: for (int i = 0; values != null && i < values.length; i++) {
1004: createInspectors().setFile(new File(values[i]));
1005: }
1006:
1007: values = line.getOptionValues('u');
1008: for (int i = 0; values != null && i < values.length; i++) {
1009: createInspectors().setURL(values[i]);
1010: }
1011:
1012: values = line.getOptionValues('l');
1013: for (int i = 0; values != null && i < values.length; i++) {
1014: ListenerEntry listenerEntry = new ListenerEntry();
1015: listenerEntry.setClassName(values[i]);
1016: addConfiguredListener(listenerEntry);
1017: }
1018:
1019: values = line.getOptionValues('W');
1020: for (int i = 0; values != null && i < values.length; i++) {
1021: createWaivers().setFile(new File(values[i]));
1022: }
1023:
1024: values = line.getOptionValues('U');
1025: for (int i = 0; values != null && i < values.length; i++) {
1026: createWaivers().setURL(values[i]);
1027: }
1028:
1029: if (line.hasOption('A')) {
1030: setArchive(new File(line.getOptionValue('A')));
1031: }
1032:
1033: //Anu 20050701 : baselining
1034: if (line.hasOption('B')) {
1035: setBaselining(line.getOptionValue('B'));
1036: }
1037: }
1038:
1039: /**
1040: * File to output waiver stubs for rejected waiver requests to. Selected waiver stubs can then be copied to waiver source. Simplifies waiver creation
1041: * @ant.non-required
1042: * @param waiverStubs
1043: */
1044: public void setWaiverStubs(File waiverStubs) {
1045: this .waiverStubs = waiverStubs;
1046: }
1047:
1048: /**
1049: * Revision mapper. Must implement com.pavelvlasov.jsel.RevisionMapper interface.
1050: * @ant.non-required
1051: * @return
1052: */
1053: public ObjectEntry createRevisionMapper() {
1054: if (revisionMapper == null) {
1055: revisionMapper = new ObjectEntry() {
1056: protected void validateClass(Class clazz)
1057: throws BuildException {
1058: super .validateClass(clazz);
1059: if (!RevisionMapper.class.isAssignableFrom(clazz)) {
1060: throw new BuildException(clazz.getName()
1061: + " doesn't implement "
1062: + RevisionMapper.class.getName());
1063: }
1064: }
1065: };
1066: return revisionMapper;
1067: } else {
1068: throw new BuildException("Revision mapper already defined");
1069: }
1070: }
1071:
1072: private File waiverStubs;
1073: private Integer severityThreshold;
1074: protected List listenerEntries = new LinkedList();
1075: ObjectEntry revisionMapper;
1076: protected boolean force = false;
1077: protected boolean evictBadInspectors = false;
1078:
1079: /**
1080: * Remove inspector from inspector set if it throws an exception
1081: * during review
1082: * @param evictBadInspectors
1083: * @ant.non-required
1084: */
1085: public void setEvictBadInspectors(boolean evictBadInspectors) {
1086: this .evictBadInspectors = evictBadInspectors;
1087: }
1088:
1089: /**
1090: * Force review even if the file is not changed
1091: * @param force
1092: * @ant.non-required
1093: */
1094: public void setForce(boolean force) {
1095: this .force = force;
1096: }
1097:
1098: //Anu 20050701 : setBaselining method moved from HammurapiTask to TaskBase
1099: /**
1100: * Sets baselining mode. Possible values:
1101: * off (default) - no baselining, on - do not report
1102: * violations stored in the baseline table, set - all violations
1103: * from current scan are saved to the baseline table.
1104: * The idea is to filter out all violations in
1105: * preexisting code and report only new violations.
1106: * Not all violations can be filtered out, only thouse
1107: * with signatures. Significant code modifications can surface some
1108: * baselined violation.
1109: * @ant.non-required
1110: * @param baselineMode
1111: */
1112: public void setBaselining(String baselineMode) {
1113: if ("off".equals(baselineMode)) {
1114: // Nothing.
1115: } else if ("on".equals(baselineMode)) {
1116: violationFilters.add(new BaselineViolationFilter());
1117: } else if ("set".equalsIgnoreCase(baselineMode)) {
1118: violationFilters.add(new BaselineSetupViolationFilter());
1119: } else {
1120: throw new BuildException("Invalid baselining mode: "
1121: + baselineMode);
1122: }
1123:
1124: }
1125:
1126: protected boolean forceOnWarnings = true;
1127:
1128: /**
1129: * Force review of files with warnings, even if the file is not changed.
1130: * Default is true
1131: * @param
1132: * @ant.non-required
1133: */
1134: public void setForceOnWarnings(boolean forceOnWarnings) {
1135: this .forceOnWarnings = forceOnWarnings;
1136: }
1137:
1138: protected File database;
1139: protected String reviewDescription;
1140:
1141: /**
1142: * Description of review, e.g. release number. Appears in history annotation.
1143: * @ant.non-required
1144: * @param baseLine
1145: */
1146: public void setReviewDescription(String reviewDescription) {
1147: this .reviewDescription = reviewDescription;
1148: }
1149:
1150: /**
1151: * If this parameter is set then Hypersonic standalone database
1152: * will be used instead of temporary database. You must set
1153: * database name if you want to run incremental reviews.
1154: * @ant.non-required
1155: * @param database
1156: */
1157: public void setDatabase(File database) {
1158: this .database = database;
1159: }
1160:
1161: protected boolean isForceOnWarnings() {
1162: return forceOnWarnings;
1163: }
1164:
1165: protected boolean isForce() {
1166: return force;
1167: }
1168:
1169: protected int tabSize = 8;
1170:
1171: /**
1172: * Tab size in source files. Defaults to 8.
1173: * @param tabSize The tabSize to set.
1174: * @ant.non-required
1175: */
1176: public void setTabSize(int tabSize) {
1177: this .tabSize = tabSize;
1178: }
1179:
1180: protected Collection violationFilters = new ArrayList();
1181:
1182: private String encoding;
1183:
1184: /**
1185: * Files encoding
1186: * @param encoding
1187: * @ant.non-required
1188: */
1189: public void setEncoding(String encoding) {
1190: this .encoding = encoding;
1191: }
1192:
1193: protected String getEncoding() {
1194: return encoding;
1195: }
1196: }
|