[Anthill-dev] Patch: Add build log scanning for warnings
Jim Hague
jim.hague at acm.org
Mon Nov 8 08:19:00 CST 2004
I wanted to be able to change the background colour of the build timestamp on
the main Anthill display from green to orange if the build completed but with
warnings.
This patch implements a simple regular expression scan of the build log after a
successful build. Currently the scanner matches up to four regular expressions
of decreasing priority against each line of the build log. Each regular
expression has an associated priority name. The highest priority name found (if
any) is attached to build log mails, and the highlight colour of the build
date/time affected.
In the patch the priority names are 'critical' (yellow), 'important' (orange),
'normal' (purple) and 'todo' (cyan). Changing names or colours is trivial,
though (gross, this) currently the priority order is defined as alphabetic
order of priority name.
Appropriate configuration has been added to the Anthill project edit screen.
--
Jim Hague - jim.hague at acm.org Never trust a computer you can't lift.
-------------- next part --------------
Index: conf/resultEmail.pgl
===================================================================
--- conf/resultEmail.pgl (revision 609)
+++ conf/resultEmail.pgl (working copy)
@@ -17,6 +17,9 @@
emailSubject.append("failed");
} else {
emailSubject.append("succeeded");
+ String warnType = _buildDef.getWarningType();
+ if (warnType != null && warnType.length() > 0)
+ emailSubject.append(", warning code " + warnType);
}
subject = emailSubject.toString();
@@ -62,4 +65,4 @@
+ buildLogFileName +
buildLogString;
%>
-<%=body%>
\ No newline at end of file
+<%=body%>
Index: conf/com.urbancode.anthill.adapter.SimpleWarningAdapter.properties
===================================================================
--- conf/com.urbancode.anthill.adapter.SimpleWarningAdapter.properties (revision
0)
+++ conf/com.urbancode.anthill.adapter.SimpleWarningAdapter.properties (revision
610)
@@ -0,0 +1,23 @@
+#
+# Defines the configuration parameters for the SimpleWarningAdapter
+# Note that the parameter importance is in alphabetical importance of
+# parameter name - thus, 'critical' is more important than 'important'
+# simply by virtue of its lower place in the sort order. You can create
+# fresh warning categories just by adding parameters in this file and
+# creating appropriately named styles in anthill.style.
+#
+param.name.1=warning.pattern.critical
+param.desc.1=A regular expression pattern. If any line in a build log matches t
his pattern, the build will be highlighted yellow on a successful build.
+param.default.1=
+
+param.name.2=warning.pattern.important
+param.desc.2=A regular expression pattern. If any line in a build log matches t
his pattern, the build will be highlighted orange on a successful build, provide
d there are no lines matching the critical pattern in the log.
+param.default.2=
+
+param.name.3=warning.pattern.normal
+param.desc.3=A regular expression pattern. If any line in a build log matches t
his pattern, the build will be highlighted purple on a successful build, provide
d there are no lines matching the critical or important patterns.
+param.default.3=
+
+param.name.4=warning.pattern.todo
+param.desc.4=A regular expression pattern. If any line in a build log matches t
his pattern, the build will be highlighted cyan on a successful build provided t
here are no lines matching any other warning pattern.
+param.default.4=
Index: projects/anthill.registry
===================================================================
--- projects/anthill.registry (revision 609)
+++ projects/anthill.registry (working copy)
@@ -14,6 +14,7 @@
anthill.mail.host = 192.168.2.203
anthill.mail.from = anthill at localhost
anthill.version.adapter = com.urbancode.anthill.adapter.UrbanCodeVersionAdapter
+anthill.warning.adapter = com.urbancode.anthill.adapter.SimpleWarningAdapter
anthill.work.dir = work
anthill.projects.dir = projects
anthill.publish.dir.default = publishDir
Index: source/main/java/com/urbancode/anthill/adapter/WarningAdapter.java
===================================================================
--- source/main/java/com/urbancode/anthill/adapter/WarningAdapter.java (revision
0)
+++ source/main/java/com/urbancode/anthill/adapter/WarningAdapter.java (revision
610)
@@ -0,0 +1,47 @@
+/*
+ * @(#)WarningAdapter.java
+ */
+package com.urbancode.anthill.adapter;
+
+import java.io.File;
+import com.urbancode.anthill.AnthillProject;
+
+/**
+ * <p>
+ * An abstract class representing a scanner for extracting a warning type
+ * from a build log file.</p>
+ *
+ * @author Jim Hague
+ */
+public abstract class WarningAdapter {
+
+ protected AnthillProject project = null;
+
+ /**
+ * Returns the AnthillProject that this WarningAdapter belongs to.
+ *
+ * @return AnthillProject that this WarningAdapter belongs to
+ */
+ public AnthillProject getAnthillProject() {
+ return project;
+ }
+
+ /**
+ * Set the AnthillProject that this WarningAdapter belongs to.
+ * This method should only be called from the WarningAdapterFactory.
+ *
+ * @paramproject the AnthillProject that this adapter belongs to
+ */
+ protected void setAnthillProject(AnthillProject project) {
+ this.project = project;
+ }
+
+ /**
+ * Search the log file and return a warning type or null if none.
+ *
+ * @param logFile the log file to scan.
+ * @return warning type, or null if none.
+ */
+ public abstract String getWarningType(File logFile)
+ throws Exception;
+}
Index: source/main/java/com/urbancode/anthill/adapter/SimpleWarningAdapter.java
===================================================================
--- source/main/java/com/urbancode/anthill/adapter/SimpleWarningAdapter.java (re
vision 0)
+++ source/main/java/com/urbancode/anthill/adapter/SimpleWarningAdapter.java (re
vision 610)
@@ -0,0 +1,214 @@
+/*
+ * @(#)WarningAdapter.java
+ */
+package com.urbancode.anthill.adapter;
+
+import org.apache.log4j.Category;
+import java.io.*;
+import java.util.*;
+import com.urbancode.anthill.AnthillProject;
+import com.urbancode.anthill.ProjectProperties;
+import com.urbancode.lib.registry.*;
+import org.apache.regexp.*;
+
+/**
+ * <p>
+ * A simple warning adapter. This just scans the log file line by line
+ * looking for a match against varions patterns. If a match is found,
+ * the associated warning type is returned.</p>
+ *
+ * @author Jim Hague
+ */
+public class SimpleWarningAdapter extends WarningAdapter {
+
+ //*************************************************************************
+ // CLASS
+ //*************************************************************************
+
+ // Create Log4j category instance for logging
+ static private Category log = Category.getInstance(SimpleWarningAdapter.cla
ss.getName());
+
+ static public final String WARNING_PATTERNS = "warning.pattern";
+
+ //*************************************************************************
+ // INSTANCE
+ //*************************************************************************
+
+ protected ProjectProperties properties = null;
+ protected Map patternMap = new HashMap();
+
+ /**
+ * Set the AnthillProject that this WarningAdapter belongs to.
+ * This method should only be called from the WarningAdapterFactory.
+ *
+ * @param the AnthillProject that this adapter belongs to
+ */
+ protected void setAnthillProject(AnthillProject project) {
+ super.setAnthillProject(project);
+ this.properties = project.getProperties();
+
+ RegistryEntry entry = properties.getPropertyRegistryEntry(WARNING_PATTERNS);
+ if (entry != null) {
+ Iterator itr = entry.getKeyIterator();
+ if (itr != null) {
+ String warnType;
+ String pattern;
+
+ synchronized (patternMap) {
+ while(itr.hasNext()) {
+ warnType = ((String) itr.next()).trim();
+ pattern = entry.getKeyValue(warnType).trim();
+ if (warnType.trim().length() > 0 && pattern.length() > 0)
+ patternMap.put(warnType, entry.getKeyValue(warnType));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Add a new type/pattern to the map.
+ *
+ * @param warnType warning type
+ * @param pattern the pattern
+ */
+ public void addWarningType(String warnType, String pattern) {
+ log.debug("add warnType " + warnType + " pattern " + pattern);
+ if (warnType == null || pattern == null)
+ return;
+
+ warnType = warnType.trim();
+ pattern = pattern.trim();
+ if (warnType.length() > 0 && pattern.length() > 0) {
+ properties.setProperty(warnType, pattern);
+ synchronized (patternMap) {
+ patternMap.put(warnType, pattern);
+ }
+ }
+ }
+
+ /**
+ * Remove a warning type from the map.
+ *
+ * @param warnType warning type
+ */
+ public void removeWarningType(String warnType) {
+ log.debug("remove warnType " + warnType);
+ RegistryEntry entry = properties.getPropertyRegistryEntry(WARNING_PATTERNS);
+ if (entry != null)
+ entry.removeKey(warnType);
+ synchronized (patternMap) {
+ patternMap.remove(warnType);
+ }
+ }
+
+ /**
+ * Return the patterns map.
+ *
+ * @return the map of warning patterns and values.
+ */
+ public Map getWarningMap() {
+ return patternMap;
+ }
+
+ /**
+ * Scan the log file looking for a warning situations. Return a
+ * string indicating a warning type, or null for no warnings.
+ * The warning patterns are searched on each line in decreasing order
+ * of warning importance. The warning type returned is the most
+ * important warning type found in the log file.
+ *
+ * @param logFile the log file to scan.
+ * @return the warning type, null if none.
+ */
+ public String getWarningType(File logFile)
+ throws Exception
+ {
+ log.info("Scan log file " + logFile + " for warnings");
+
+ // Create an array of Warning, sorted into order of importance.
+ Warning[] matchers;
+ Iterator itr;
+ int patNo = 0;
+
+ synchronized(patternMap) {
+ if (patternMap.isEmpty()) {
+ return null;
+ }
+
+ matchers = new Warning[patternMap.size()];
+ for ( itr = patternMap.keySet().iterator(); itr.hasNext(); ) {
+ try {
+ String wtype = (String) itr.next();
+ String pattern = (String) patternMap.get(wtype);
+ RE re = new RE(pattern);
+ matchers[patNo++] = new Warning(wtype, re);
+ } catch (RESyntaxException rse) {
+ log.error("bad pattern " + rse);
+ }
+ }
+ }
+ Arrays.sort(matchers);
+
+ // Read out and grep someone.
+ BufferedReader r = new BufferedReader(new FileReader(logFile));
+ String line;
+ String res = null;
+
+ // Consider all matches under this priority. If this hits zero,
+ // we've found a maximum priority warning in the file, so don't
+ // bother with the rest of the file.
+ int maxPatNo = matchers.length;
+ int i;
+
+ while (maxPatNo > 0 && (line = r.readLine()) != null) {
+ // Don't try to match against empty lines.
+ if ( line.length() == 0 )
+ continue;
+
+ for (patNo = 0; patNo < maxPatNo; patNo++) {
+ if (matchers[patNo].getPattern().match(line)) {
+ res = matchers[patNo].getType();
+ maxPatNo = patNo;
+ break;
+ }
+ }
+ }
+ r.close();
+
+ return res;
+ }
+}
+
+class Warning
+ implements Comparable
+{
+ String wtype;
+ RE pattern;
+
+ public Warning(String wtype, RE pattern)
+ {
+ this.wtype = wtype;
+ this.pattern = pattern;
+ }
+
+ public int compareTo(Object o)
+ {
+ if ( o instanceof Warning )
+ return wtype.compareTo(((Warning) o).wtype);
+ else
+ throw new ClassCastException("Can only compare Warnings with Warnings");
+ }
+
+ public String getType()
+ {
+ return wtype;
+ }
+
+ public RE getPattern()
+ {
+ return pattern;
+ }
+}
+
+
Index: source/main/java/com/urbancode/anthill/adapter/WarningAdapterFactory.java
===================================================================
--- source/main/java/com/urbancode/anthill/adapter/WarningAdapterFactory.java (r
evision 0)
+++ source/main/java/com/urbancode/anthill/adapter/WarningAdapterFactory.java (r
evision 610)
@@ -0,0 +1,41 @@
+/*
+ * @(#)WarningAdapterFactory.java
+ *
+ */
+
+package com.urbancode.anthill.adapter;
+import com.urbancode.anthill.AnthillProject;
+
+/**
+ * <p>
+ * This is a factory to create <code>WarningAdapter</code> classes.</p>
+ *
+ * @author Jim Hague
+ */
+public class WarningAdapterFactory {
+
+ /**
+ * Create the specified <code>WarningAdapter</code>.
+ *
+ * @param warningAdapter the full classname of the adapter including
+ * the package
+ * @param versionFile the filename of the version file
+ * @return the requested <code>WarningAdapter</code>
+ */
+ static public WarningAdapter getWarningAdapter(AnthillProject project,
+ String warningAdapter)
+ throws Exception {
+
+ WarningAdapter adapter = null;
+
+ try {
+ adapter = (WarningAdapter) Class.forName(warningAdapter).newInstanc
e();
+ adapter.setAnthillProject(project);
+ } catch (Exception e) {
+ throw new Exception("Unable to create warning adapter: " +
+ warningAdapter);
+ }
+
+ return adapter;
+ }
+}
Index: source/main/java/com/urbancode/anthill/BuildDefinition.java
===================================================================
--- source/main/java/com/urbancode/anthill/BuildDefinition.java (revision 609)
+++ source/main/java/com/urbancode/anthill/BuildDefinition.java (working copy)
@@ -22,6 +22,7 @@
//*************************************************************************
*
// INSTANCE
//*************************************************************************
*
+ protected String warningType = null;
protected boolean errorFlag = false;
protected boolean loginErrorFlag = false;
protected boolean forceBuildFlag = false;
@@ -32,6 +33,7 @@
protected StringBuffer logMessageBuffer = new StringBuffer();
protected List revisionList = null;
protected List antParamList = new ArrayList();
+ protected String buildLogFileName = null;
//-------------------------------------------------------------------------
-
public BuildDefinition() {
@@ -43,6 +45,16 @@
}
//-------------------------------------------------------------------------
-
+ public void setWarningType(String warningType) {
+ this.warningType = warningType;
+ }
+
+ //-------------------------------------------------------------------------
-
+ public String getWarningType() {
+ return warningType;
+ }
+
+ //-------------------------------------------------------------------------
-
public void setErrorFlag(boolean errorFlag) {
this.errorFlag = errorFlag;
}
@@ -153,6 +165,16 @@
}
//-------------------------------------------------------------------------
-
+ public String getBuildLogFileName() {
+ return buildLogFileName;
+ }
+
+ //-------------------------------------------------------------------------
-
+ public void setBuildLogFileName(String buildLogFileName) {
+ this.buildLogFileName = buildLogFileName;
+ }
+
+ //-------------------------------------------------------------------------
-
public void run() {
log.debug("running BuildDefinition ForceBuild flag" +this.getForceBuild
Flag());
project.releaseProject(this);
Index: source/main/java/com/urbancode/anthill/AnthillProject.java
===================================================================
--- source/main/java/com/urbancode/anthill/AnthillProject.java (revision 609)
+++ source/main/java/com/urbancode/anthill/AnthillProject.java (working copy)
@@ -180,6 +180,11 @@
}
//-------------------------------------------------------------------------
-
+ public WarningAdapter getWarningAdapter() {
+ return properties.getWarningAdapter();
+ }
+
+ //-------------------------------------------------------------------------
-
/**
* Implementation of Buildable
*/
Index: source/main/java/com/urbancode/anthill/ProjectProperties.java
===================================================================
--- source/main/java/com/urbancode/anthill/ProjectProperties.java (revision 609)
+++ source/main/java/com/urbancode/anthill/ProjectProperties.java (working copy)
@@ -75,6 +75,7 @@
static public final String VERSION_PROPERTIES = "version";
static public final String REPOSITORY_ADAPTER = "repository.adapter";
static public final String REPOSITORY_PROPERTIES = "repository";
+ static public final String WARNING_ADAPTER = "warning.adapter";
static public final String SCHEDULE_KEY = "schedule";
static public final String MAIL_HOST_KEY = "mail.host";
static public final String MAIL_FROM_KEY = "mail.from";
@@ -82,6 +83,7 @@
static public final String LAST_GOOD_BUILD_DATE_KEY = "lastGoodBuildDate";
static public final String LAST_BUILD_FAIL_DATE_KEY = "lastBuildFailDate";
static public final String LAST_BUILD_SUCCEEDED_KEY = "lastBuildSucceeded";
+ static public final String LAST_BUILD_WARNING_TYPE_KEY = "lastBuildWarningT
ype";
static public final String ANTHILL_URL_KEY = "server";
static public final String PUBLISH_URL_KEY = "publish.url";
static public final String LOCK_VERSION_KEY = "lock.version.file";
@@ -121,10 +123,12 @@
protected RepositoryAdapter repositoryAdapter = null;
protected VersionAdapter versionAdapter = null;
+ protected WarningAdapter warningAdapter = null;
protected AnthillSchedule schedule = null;
protected String repositoryAdapterName = null;
protected String versionAdapterName = null;
+ protected String warningAdapterName = null;
protected String scheduleName = null;
protected String anthillUrl = null;
protected String publishUrl = null;
@@ -144,6 +148,7 @@
protected String lastGoodBuildDate = null;
protected String lastBuildFailDate = null;
protected String lastBuildSucceeded = null;
+ protected String lastBuildWarningType = null;
// protected String lockVersion = null;
// protected String versionFilePath = null;
protected String buildScriptPath = null;
@@ -240,6 +245,11 @@
}
//-------------------------------------------------------------------------
-
+ public RegistryEntry getPropertyRegistryEntry(String entryName) {
+ return projectRegEntry.getChildRegistryEntry(entryName);
+ }
+
+ //-------------------------------------------------------------------------
-
public RepositoryAdapter getRepositoryAdapter() {
if (repositoryAdapter == null ||
!repositoryAdapter.getClass().getName().equals(repositoryAdapterNam
e)) {
@@ -301,6 +311,35 @@
}
//-------------------------------------------------------------------------
-
+ public WarningAdapter getWarningAdapter() {
+ if (warningAdapter == null ||
+ !warningAdapter.getClass().getName().equals(warningAdapterName)) {
+
+ try {
+ warningAdapter = WarningAdapterFactory.getWarningAdapter(
+ project, warningAdapterName);
+ } catch (Exception e) {
+ throw new IllegalStateException("exception while getting " +
+ warningAdapterName + " instance: " + e.getMessage());
+ }
+ }
+
+ return warningAdapter;
+ }
+
+ //-------------------------------------------------------------------------
-
+ public String getWarningAdapterName() {
+ return warningAdapterName;
+ }
+
+ //-------------------------------------------------------------------------
-
+ public void setWarningAdapterName(String warningAdapterName) {
+ setProperty(WARNING_ADAPTER, warningAdapterName);
+ this.warningAdapterName = warningAdapterName;
+ warningAdapter = null;
+ }
+
+ //-------------------------------------------------------------------------
-
public AnthillSchedule getSchedule() {
return schedule;
}
@@ -411,6 +450,19 @@
}
//-------------------------------------------------------------------------
-
+ public String getLastBuildWarningType() {
+ return lastBuildWarningType;
+ }
+
+ //-------------------------------------------------------------------------
-
+ public void setLastBuildWarningType(String warningType) {
+ if (warningType == null)
+ warningType = "";
+ setProperty(LAST_BUILD_WARNING_TYPE_KEY, warningType);
+ this.lastBuildWarningType = warningType;
+ }
+
+ //-------------------------------------------------------------------------
-
public boolean isTagAllBuildsSelected() {
return TAG_BUILD_ALL.equalsIgnoreCase(tagBuild);
}
@@ -738,6 +790,11 @@
regEntry, VERSION_ADAPTER, versionAdapterName);
versionAdapter = null;
+ // setup Warning Adapter Name
+ warningAdapterName = getPropValue(
+ regEntry, WARNING_ADAPTER, warningAdapterName);
+ warningAdapter = null;
+
// setup Schedule Name
scheduleName = getPropValue(regEntry, SCHEDULE_KEY, scheduleName);
if (scheduleName != null) {
@@ -768,6 +825,10 @@
lastBuildSucceeded = getPropValue(
regEntry, LAST_BUILD_SUCCEEDED_KEY, lastBuildSucceeded);
+ // setup Last Build Had Warnings
+ lastBuildWarningType = getPropValue(
+ regEntry, LAST_BUILD_WARNING_TYPE_KEY, lastBuildWarningType);
+
// setup Last Good Build Date
lastGoodBuildDate = getPropValue(
regEntry, LAST_GOOD_BUILD_DATE_KEY, lastGoodBuildDate);
Index: source/main/java/com/urbancode/anthill/BuildManager.java
===================================================================
--- source/main/java/com/urbancode/anthill/BuildManager.java (revision 609)
+++ source/main/java/com/urbancode/anthill/BuildManager.java (working copy)
@@ -27,6 +27,7 @@
import com.urbancode.anthill.adapter.VersionAdapter;
import com.urbancode.anthill.adapter.RepositoryAdapter;
+import com.urbancode.anthill.adapter.WarningAdapter;
import com.urbancode.anthill.adapter.PerforceRepositoryAdapter;
import com.urbancode.anthill.adapter.RepositoryException;
import com.urbancode.anthill.adapter.Revision;
@@ -72,12 +73,14 @@
RepositoryAdapter radapter = null;
VersionAdapter vadapter = null;
+ WarningAdapter wadapter = null;
boolean doBuild = false;
Date buildDate = null;
try {
radapter = project.getRepositoryAdapter();
vadapter = project.getVersionAdapter();
+ wadapter = project.getWarningAdapter();
def.appendLogMessage("Anthill version " + Anthill.getVersion() + "\
n\n");
@@ -199,7 +202,17 @@
log.info("Step 7) Publish Project: ");
publish(def);
}
-
+
+ if ( !def.getErrorFlag() ) {
+ log.info("Step 8) Scan build log for warnings: ");
+ if (wadapter != null) {
+
+ String warnType =
+ wadapter.getWarningType(new File(def.getBuildLogFileName()));
+ def.setWarningType(warnType);
+ properties.setLastBuildWarningType(warnType);
+ }
+ }
}
catch (Throwable e) {
log.error(e.getMessage(), e);
@@ -401,7 +414,7 @@
log.info("Build Project: ");
buildProject(buildDef);
-
+
buildDef.appendLogMessage("Build: OK\n");
buildDef.appendLogMessage(logMessage.toString());
}
@@ -473,6 +486,7 @@
}
cmdList.add("-logfile");
cmdList.add(logFile);
+ buildDef.setBuildLogFileName(logFile);
// add project ant params
Iterator keys = properties.getBuildAntParams().iterator();
Index: source/main/java/com/urbancode/anthill/web/admin/ProjectPropertiesUpdateS
ervlet.java
===================================================================
--- source/main/java/com/urbancode/anthill/web/admin/ProjectPropertiesUpdateServ
let.java (revision 609)
+++ source/main/java/com/urbancode/anthill/web/admin/ProjectPropertiesUpdateServ
let.java (working copy)
@@ -126,6 +126,7 @@
if (propName.startsWith("version") ||
propName.startsWith("repository") ||
+ propName.startsWith("warning") ||
propName.startsWith("profile") ||
propName.startsWith("build") ||
propName.startsWith("publish") ||
@@ -229,7 +230,8 @@
if (!error) {
req.setAttribute(WebKeys.ProjectKey, project);
if ((fromPropPageName.equals(ScreenNames.repositoryPropScreen)) ||
- (fromPropPageName.equals(ScreenNames.versionAdapterPropScreen))
) {
+ (fromPropPageName.equals(ScreenNames.versionAdapterPropScreen))
||
+ (fromPropPageName.equals(ScreenNames.warningAdapterPropScreen))
) {
context.getRequestDispatcher(ScreenNames.projectPropScreen).for
ward(req, res);
}
else {
Index: source/main/java/com/urbancode/anthill/web/admin/ScreenNames.java
===================================================================
--- source/main/java/com/urbancode/anthill/web/admin/ScreenNames.java (revision
609)
+++ source/main/java/com/urbancode/anthill/web/admin/ScreenNames.java (working c
opy)
@@ -37,6 +37,7 @@
String profilePropScreen = "/profileProperties.jsp";
String scheduleScreen = "/schedule.jsp";
String versionAdapterPropScreen = "/versionAdapterProperties.jsp";
+ String warningAdapterPropScreen = "/warningAdapterProperties.jsp";
String emptyPropScreen = "/emptyProperties.jsp";
String newBuildProjectScreen = "/specImplBuildProject.jsp";
String AnthillAdminServlet = "/AnthillAdminServlet";
Index: source/main/java/com/urbancode/anthill/web/admin/WarningAdapterProperties
ViewServlet.java
===================================================================
--- source/main/java/com/urbancode/anthill/web/admin/WarningAdapterPropertiesVie
wServlet.java (revision 0)
+++ source/main/java/com/urbancode/anthill/web/admin/WarningAdapterPropertiesVie
wServlet.java (revision 610)
@@ -0,0 +1,139 @@
+/*
+ * @(#)WarningAdapterPropertiesViewServlet.java
+ */
+package com.urbancode.anthill.web.admin;
+
+import org.apache.log4j.Category;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import com.urbancode.anthill.*;
+
+import java.net.URL;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import java.util.Properties;
+
+/**
+ *
+ * @author jim.hague at acm.org
+ */
+public class WarningAdapterPropertiesViewServlet extends AnthillBaseServlet {
+
+ //*************************************************************************
*
+ // CLASS
+ //*************************************************************************
*
+
+ // Create Log4j category instance for logging
+ static private Category log = Category.getInstance(WarningAdapterProperties
ViewServlet.class.getName());
+
+ //*************************************************************************
*
+ // INSTANCE
+ //*************************************************************************
*
+
+ /** Processes requests for both HTTP <code>GET</code> and <code>POST</code>
methods.
+ * @param request servlet request
+ * @param response servlet response
+ */
+ protected void processRequest(HttpServletRequest req, HttpServletResponse r
es)
+ throws ServletException, java.io.IOException {
+ log.debug("Processing request for WarningAdapterPropertiesViewServlet")
;
+ ServletContext context = getServletContext();
+ Anthill anthill = (Anthill)context.getAttribute(WebKeys.AnthillKey);
+ AnthillProject project = null;
+ String projectName = req.getParameter(WebKeys.ProjectNameKey);
+ log.debug("projectName: " + projectName);
+ boolean error = false;
+ String errorMessage = null;
+
+ if (projectName != null) {
+ project = anthill.getProject(projectName);
+ String adapterName =
+ project.getProperties().getWarningAdapterName();
+ log.debug("adapterName: " + adapterName);
+ try {
+ Properties props = loadAdapterConfigOptions(adapterName);
+ if (project != null) {
+ req.setAttribute(WebKeys.AnthillKey, anthill);
+ req.setAttribute(WebKeys.ProjectKey, project);
+ req.setAttribute(WebKeys.RepositoryConfigKey, props);
+ } else {
+ error = true;
+ errorMessage = "Could not find project with name: "+project
Name;
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ error = true;
+ errorMessage = e.getMessage();
+ }
+ } else {
+ error = true;
+ errorMessage = "ProjectName parameter can not be null";
+ }
+
+ if (error) {
+ req.setAttribute(WebKeys.errorMessageKey, errorMessage);
+ context.getRequestDispatcher(ScreenNames.errorScreen).forward(req ,
res);
+ } else {
+ Properties tempProps = (Properties)req.getAttribute(WebKeys.Reposit
oryConfigKey);
+ if (tempProps.isEmpty()) {
+ context.getRequestDispatcher(ScreenNames.emptyPropScreen).forwa
rd(req, res);
+ }
+ else {
+ context.getRequestDispatcher(ScreenNames.warningAdapterPropScre
en).forward(req , res);
+ }
+ }
+ }
+
+ /** Returns a short description of the servlet.
+ */
+ public String getServletInfo() {
+ return "Short description";
+ }
+
+ private Properties loadAdapterConfigOptions(String adapterName)
+ throws Exception {
+ Anthill anthill = null;
+ try{
+ anthill = Anthill.getAnthill();
+ }
+ catch(Exception e){
+ log.error("ANTHILL SINGLETON" + e.getMessage().toString());
+ }
+
+ log.debug("Loading " + adapterName);
+ String adapterConfigFileName = anthill.getAnthillRootDir().getAbsoluteP
ath() +
+ File.separator + "conf" + File.separator +
+ adapterName + ".properties";
+ log.debug("adapterConfigFileName " + adapterConfigFileName);
+
+ Properties config_list = new Properties();
+ InputStream rf = null;
+ try {
+ rf = new FileInputStream(new File(adapterConfigFileName));
+ if (rf == null) {
+ String msg = "Error creating inputstream for properties file: " + adapterCo
nfigFileName;
+ log.error(msg);
+ throw new IOException(msg);
+ }
+ config_list.load(rf);
+ log.debug("Loaded properties file: " + adapterConfigFileName);
+ }
+ finally {
+ try {
+ if (rf != null){
+ rf.close();
+ }
+ }
+ catch (IOException e){
+ }
+ }
+ return config_list;
+ }
+
+}
Index: source/main/webAdmin/main.jsp
===================================================================
--- source/main/webAdmin/main.jsp (revision 609)
+++ source/main/webAdmin/main.jsp (working copy)
@@ -63,7 +63,11 @@
if (wasBuildGood) {
buildDate = props.getLastGoodBuildDate();
if (buildDate != null) {
- buildStatusClass = "succeeded";
+ String warning = props.getLastBuildWarningType();
+ buildStatusClass =
+ (warning == null || warning.length() == 0)
+ ? "succeeded"
+ : "warning-" + warning;
buildDateStr = dtFormat.format(buildDate);
}
}
@@ -210,4 +214,4 @@
Running on Java <%= System.getProperty("java.version") %></div>
</body>
-</html>
\ No newline at end of file
+</html>
Index: source/main/webAdmin/WEB-INF/web.xml
===================================================================
--- source/main/webAdmin/WEB-INF/web.xml (revision 609)
+++ source/main/webAdmin/WEB-INF/web.xml (working copy)
@@ -110,6 +110,10 @@
<servlet-class>com.urbancode.anthill.web.admin.VersionAdapterPropertiesViewSe
rvlet</servlet-class>
</servlet>
<servlet>
+ <servlet-name>WarningAdapterPropertiesViewServlet</servlet-name>
+ <servlet-class>com.urbancode.anthill.web.admin.WarningAdapterPropertiesViewSe
rvlet</servlet-class>
+ </servlet>
+ <servlet>
<servlet-name>ViewProjectServlet</servlet-name>
<servlet-class>com.urbancode.anthill.web.admin.ViewProjectServlet</servlet-cl
ass>
</servlet>
@@ -226,6 +230,10 @@
<url-pattern>/VersionAdapterPropertiesViewServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
+ <servlet-name>WarningAdapterPropertiesViewServlet</servlet-name>
+ <url-pattern>/WarningAdapterPropertiesViewServlet</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
<servlet-name>ViewProjectServlet</servlet-name>
<url-pattern>/projects/*</url-pattern>
</servlet-mapping>
Index: source/main/webAdmin/style/anthillStyle.jsp
===================================================================
--- source/main/webAdmin/style/anthillStyle.jsp (revision 609)
+++ source/main/webAdmin/style/anthillStyle.jsp (working copy)
@@ -80,6 +80,22 @@
background-color: #00FF00;
}
+TD.warning-critical {
+ background-color: #FFFF00;
+}
+
+TD.warning-important {
+ background-color: #FF7F00;
+}
+
+TD.warning-normal {
+ background-color: #FF00FF;
+}
+
+TD.warning-todo {
+ background-color: #00FFFF;
+}
+
TD.failed {
background-color: #FF0000;
}
Index: source/main/webAdmin/projectProperties.jsp
===================================================================
--- source/main/webAdmin/projectProperties.jsp (revision 609)
+++ source/main/webAdmin/projectProperties.jsp (working copy)
@@ -22,6 +22,9 @@
String versionAdapter = properties.getVersionAdapterName();
if (versionAdapter == null) versionAdapter = "";
+ String warningAdapter = properties.getWarningAdapterName();
+ if (warningAdapter == null) warningAdapter = "";
+
// String versionFile = properties.getVersionFilePath();
// if (versionFile == null) versionFile = "";
@@ -104,6 +107,23 @@
<tr>
<td class="description" colspan="3">
+ The class name of the warning adapter. The warning adapter
+ classifies message in the build log into status warnings.
+ </td>
+ </tr>
+ <tr>
+ <td>anthill.warning.adapter</td>
+ <td align="left" colspan="2">
+ <input type="text"
+ name="warning.adapter"
+ value="<%= warningAdapter %>"
+ size="72">
+ <a href="WarningAdapterPropertiesViewServlet?ProjectName=<%=projectName%>
">Configure <%=project.getProperties().getWarningAdapterName()%></a>
+ </td>
+ </tr>
+
+ <tr>
+ <td class="description" colspan="3">
The paths to the build script relative to the project root directory.
</td>
</tr>
Index: source/main/webAdmin/warningAdapterProperties.jsp
===================================================================
--- source/main/webAdmin/warningAdapterProperties.jsp (revision 0)
+++ source/main/webAdmin/warningAdapterProperties.jsp (revision 610)
@@ -0,0 +1,71 @@
+<%@ page contentType="text/html"%>
+<%@ page import="com.urbancode.lib.registry.RegistryEntry" %>
+<%@ page import="com.urbancode.anthill.*" %>
+<%@ page import= "com.urbancode.anthill.web.admin.WebKeys" %>
+<%@ page import= "com.urbancode.anthill.web.admin.ScreenNames" %>
+<%@ page import= "java.util.*" %>
+<html>
+<head>
+ <title>WarningAdapter Properties</title>
+ <link rel="stylesheet" type="text/css" href="<%= request.getContextPath() %>/
style/anthillStyle.jsp">
+</head>
+<body>
+<%
+ Anthill anthill = (Anthill)request.getAttribute(WebKeys.AnthillKey);
+ AnthillProject project = (AnthillProject)request.getAttribute(WebKeys.Project
Key);
+ ProjectProperties properties = project.getProperties();
+ Properties adapterProperties = (Properties)request.getAttribute(WebKeys.Repos
itoryConfigKey);
+
+ String projectName = project.getProjectName();
+ if (projectName == null) projectName = "";
+
+%>
+
+<h2><%= properties.getWarningAdapterName() %> Properties</h2>
+
+<form action="ProjectPropertiesUpdateServlet" method="POST">
+<input type="hidden"
+ name="<%= WebKeys.ProjectNameKey %>"
+ value="<%= projectName %>">
+
+<input type="hidden"
+ name="<%= WebKeys.FromPropPageKey %>"
+ value="<%=ScreenNames.warningAdapterPropScreen%>">
+
+<table align="center" cellpadding="3" cellspacing="0" border="1" width="600">
+<%
+String name = null;
+int i = 1;
+while ((name = adapterProperties.getProperty("param.name." + i)) != null) {
+ String description = adapterProperties.getProperty("param.desc." + i);
+ String def = adapterProperties.getProperty("param.default." + i);
+ String value = properties.getProperty(name) == null ? def : properties.getP
roperty(name);
+%>
+ <tr>
+ <td class="description" colspan="3"><%=description%></td>
+ </tr>
+ <tr>
+ <td width="150"><%=name%></td>
+ <td align="left" colspan="2">
+ <input type="text"
+ name="<%=name%>"
+ value="<%=value == null ? "" : value%>"
+ size="72">
+ </td>
+ </tr>
+<%
+ i++;
+}
+%>
+ <tr>
+ <td class="buttons" colspan="3"><input type="submit" name="Update" value="U
pdate"></td>
+ </tr>
+</table>
+</form>
+
+<br>
+<div class="version"><hr align="center" width="80%">
+Anthill version <%= Anthill.getVersion() %></div>
+
+</body>
+</html>
More information about the Anthill-dev
mailing list