package hudson.plugins.violations.parse;
import hudson.plugins.violations.model.FullBuildModel;
import hudson.plugins.violations.model.FullFileModel;
import hudson.util.IOException2;
import java.io.IOException;
import java.io.InputStream;
import java.io.File;
import java.util.Locale;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import hudson.plugins.violations.ViolationsParser;
public abstract class ViolationsDOMParser
implements ViolationsParser {
private FullBuildModel model;
private File projectPath;
private String[] sourcePaths;
private Document dom;
/**
* Get the parsed document.
* @return the document.
*/
public Document getDocument() {
return dom;
}
/*
* Parse a violations file.
* @param model the model to store the violations in.
* @param projectPath the project path used for resolving paths.
* @param fileName the name of the violations file to parse
* (relative to the projectPath).
* @param sourcePaths a list of source paths to resolve classes against
* @throws IOException if there is an error.
*/
public void parse(
FullBuildModel model,
File projectPath,
String fileName,
String[] sourcePaths)
throws IOException {
boolean success = false;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
dom = db.parse(new File(projectPath, fileName));
setProjectPath(projectPath);
setModel(model);
setSourcePaths(sourcePaths);
execute();
success = true;
} catch (IOException ex) {
throw ex;
} catch (Exception ex) {
throw new IOException2("Cannot parse " + fileName, ex);
} finally {
// ? terminate the parser
}
}
protected abstract void execute()
throws IOException, Exception;
/**
* Set the build model.
* @param model the model.
*/
public void setModel(FullBuildModel model) {
this.model = model;
}
/**
* Get the build model.
* @return the build model.
*/
protected FullBuildModel getModel() {
return model;
}
/**
* Set the project path.
* This is used to get a relative name for files.
* @param projectPath the project path.
*/
public void setProjectPath(File projectPath) {
this.projectPath = projectPath;
}
/**
* Get the project path.
* @return the project path.
*/
protected File getProjectPath() {
return projectPath;
}
/**
* Set the source paths attribute.
* This is used to resolve classes against.
* @param sourcePaths the value to use
*/
public void setSourcePaths(String[] sourcePaths) {
this.sourcePaths = sourcePaths;
}
/**
* Get the source paths.
* @return the source paths.
*/
protected String[] getSourcePaths() {
return sourcePaths;
}
// -----------------------------------------------
//
// Utility methods
//
// -----------------------------------------------
/**
* Get the full file model for a particular relative name and
* source file.
* @param name the relative file name.
* @param sourceFile the source file for the file.
* @return the full file model.
*/
protected FullFileModel getFileModel(String name, File sourceFile) {
FullFileModel fileModel = model.getFileModel(name);
File other = fileModel.getSourceFile();
if (sourceFile == null
|| ((other != null) && (
other.equals(sourceFile)
|| other.exists()))) {
return fileModel;
}
fileModel.setSourceFile(sourceFile);
fileModel.setLastModified(sourceFile.lastModified());
return fileModel;
}
/**
* Get the full file model object for an absolute name.
* @param absoluteName the absolute name of the file.
* @return the file model object.
*/
protected FullFileModel getFileModel(String absoluteName) {
File file = new File(absoluteName);
String name = resolveName(absoluteName);
return getFileModel(name, file);
}
/**
* Fix an absolute path.
* Some paths in some violations file contain a ..
* this causes grief.
* @param abs the absolute name.
* @return a fixed name.
* @throws IOException if there is a problem.
*/
protected String fixAbsolutePath(String abs) throws IOException {
if (abs.contains("..")) {
return new File(abs).getCanonicalPath();
} else {
return abs;
}
}
/**
* Resolve an absolute name agaist the project path.
* @param absoluteName the absolute name.
* @return a path relative to the project path or an absolute
* name if the name cannot be resolved.
*/
protected String resolveName(String absoluteName) {
String remote = projectPath.getAbsolutePath().replace('\\', '/');
String lcRemote = remote.toLowerCase(Locale.US);
String name = absoluteName.replace('\\', '/');
String lcName = name.toLowerCase(Locale.US);
if (lcName.startsWith(lcRemote)) {
name = name.substring(lcRemote.length());
} else {
// for absolute name discard dos drive
int colPos = name.indexOf(':');
int dirPos = name.indexOf('/');
if (colPos != -1 && (dirPos == -1 || dirPos > colPos)) {
name = name.substring(colPos + 1);
}
}
// if name starts with a / strip it.
if (name.startsWith("/")) {
name = name.substring(1);
}
return name;
}
/**
* Get an int from an attribute.
* @return the int or 0 if it does not exist or is malformed.
*/
public int getInt(Element el, String attribute) {
String v = el.getAttribute(attribute);
try {
return Integer.parseInt(v);
} catch (Exception ex) {
return 0;
}
}
/**
* Get an attribute.
* @return the attribute value.
* @throws Exception if the attribute is not there or is blank.
*/
public String checkNotBlank(Element el, String attribute)
throws Exception {
String ret = el.getAttribute(attribute);
if (ret == null || ret.trim().equals("")) {
throw new Exception(
"Expecting attribute " + attribute
+ " in element " + el.getLocalName());
}
return ret;
}
}