/******************************************************************************** * CruiseControl, a Continuous Integration Toolkit * Copyright (c) 2007, ThoughtWorks, Inc. * 200 E. Randolph, 25th Floor * Chicago, IL 60601 USA * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * + Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * + Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the * names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************************/ package net.sourceforge.cruisecontrol.dashboard.service; import net.sourceforge.cruisecontrol.dashboard.BuildDetail; import net.sourceforge.cruisecontrol.dashboard.BuildLiveDetail; import net.sourceforge.cruisecontrol.dashboard.CurrentStatus; import net.sourceforge.cruisecontrol.dashboard.LogFile; import net.sourceforge.cruisecontrol.dashboard.PreviousResult; import net.sourceforge.cruisecontrol.dashboard.exception.ShouldStopParsingException; import net.sourceforge.cruisecontrol.dashboard.saxhandler.BasicInfoExtractor; import net.sourceforge.cruisecontrol.dashboard.saxhandler.CompositeExtractor; import net.sourceforge.cruisecontrol.dashboard.saxhandler.DurationExtractor; import net.sourceforge.cruisecontrol.dashboard.saxhandler.ModificationExtractor; import net.sourceforge.cruisecontrol.dashboard.saxhandler.StackTraceExtractor; import net.sourceforge.cruisecontrol.dashboard.saxhandler.TestSuiteExtractor; import net.sourceforge.cruisecontrol.dashboard.utils.functors.BuildSummariesFilters; import net.sourceforge.cruisecontrol.dashboard.utils.functors.SpecificLogFileFilter; import org.apache.log4j.Logger; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class BuildService { private static final Logger LOGGER = Logger.getLogger(BuildService.class); private final ConfigurationService configuration; private final BuildLoopQueryService queryService; public BuildService(ConfigurationService configuration, BuildLoopQueryService queryService) { this.configuration = configuration; this.queryService = queryService; } public BuildLiveDetail getActiveBuild(final String projectName, PreviousResult previousResult) { return new BuildLiveDetail(projectName, previousResult); } public BuildDetail getBuild(String projectName, String yyyyMMddssHHmmss) { BuildDetail build = createBuildFromFile(getBuildFile(projectName, yyyyMMddssHHmmss)); if (queryService.isDiscontinued(projectName)) { build.updateStatus(CurrentStatus.DISCONTINUED); } else if (isPaused(projectName)) { build.updateStatus(CurrentStatus.PAUSED); } return build; } private boolean isPaused(String projectName) { String status = queryService.getProjectStatus(projectName); return CurrentStatus.PAUSED.equals(CurrentStatus.getProjectBuildStatus(status)); } private LogFile getBuildFile(String projectName, final String yyyyMMddssHHmmss) { File logRoot = configuration.getLogRoot(projectName); File[] files = logRoot.listFiles(new SpecificLogFileFilter(yyyyMMddssHHmmss)); return new LogFile(logRoot, files[0].getName()); } BuildDetail createBuildFromFile(LogFile logFile) { try { Map properties = new HashMap(); parseLogFile(logFile, properties); properties.put("artifactfolder", getArtifactsRootDir((String) properties.get("projectname"))); return new BuildDetail(logFile, properties); } catch (Exception e) { e.printStackTrace(); LOGGER.error("Can not parse the log file: " + logFile.getAbsolutePath(), e); return null; } } private void parseLogFile(LogFile buildLogFile, Map props) throws Exception { CompositeExtractor compositeExtractor = compositeExtractor(buildLogFile); parse(buildLogFile.getInputStream(), compositeExtractor); compositeExtractor.report(props); } private void parse(InputStream logFileInputStream, CompositeExtractor compositeExtractor) throws Exception { SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser(); try { saxParser.parse(logFileInputStream, compositeExtractor); } catch (ShouldStopParsingException e) { LOGGER.debug("Intentionally throwing exception to stop parsing."); } } private CompositeExtractor compositeExtractor(File buildLogFile) { List handlers = defaultExtractors(); if (!succeeded(buildLogFile)) { handlers.add(new StackTraceExtractor()); } return new CompositeExtractor(handlers); } private List defaultExtractors() { List extractors = new ArrayList(); extractors.add(new DurationExtractor()); extractors.add(new ModificationExtractor()); extractors.add(new BasicInfoExtractor()); extractors.add(new TestSuiteExtractor()); return extractors; } private boolean succeeded(File buildLogFile) { return BuildSummariesFilters.succeedFilter().accept(buildLogFile.getParentFile(), buildLogFile.getName()); } private File getArtifactsRootDir(String projectName) { File artifactRoot = configuration.getArtifactRoot(projectName); if (artifactRoot == null) { return new File("could/not/find/artifactsfolder/for/" + projectName); } return artifactRoot; } }