boolean hidden = Boolean.valueOf(cloudNode.valueOf("@hidden")) && !cloudId.equals(CloudFactory.DEFAULT_CLOUD);
Class<? extends Cloud> cloudClass = getClass(classLoader, cloudClassname, Cloud.class);
Class<? extends NameLookup> usernameClass = getClass(classLoader, usernameClassname, NameLookup.class);
Node cloudMessageNode = findMessageNode(messageCollectionList, "/MessageCollection/Cloud[@id='" + cloudId + "']",
"Missing Cloud description for cloud " + cloudId);
String description = getChildText(cloudMessageNode, "Description").trim();
String details = getChildText(cloudMessageNode, "Details").trim();
PropertyBundle properties = new PropertyBundle();
if (propertiesLocation != null && propertiesLocation.length() > 0) {
URL properiesURL = classLoader.getResource(propertiesLocation);
if (properiesURL == null) {
continue;
}
properties.loadPropertiesFromURL(properiesURL);
}
List<Node> propertyNodes = XMLUtil.selectNodes(cloudNode, "Property");
for (Node node : propertyNodes) {
String key = node.valueOf("@key");
String value = node.getText().trim();
properties.setProperty(key, value);
}
CloudPlugin cloudPlugin = new CloudPluginBuilder().setFindbugsPluginId(plugin.getPluginId()).setCloudid(cloudId).setClassLoader(classLoader)
.setCloudClass(cloudClass).setUsernameClass(usernameClass).setHidden(hidden).setProperties(properties)
.setDescription(description).setDetails(details).setOnlineStorage(onlineStorage).createCloudPlugin();
plugin.addCloudPlugin(cloudPlugin);
}
// Create PluginComponents
try {
List<Node> componentNodeList = XMLUtil.selectNodes(pluginDescriptor, "/FindbugsPlugin/PluginComponent");
for (Node componentNode : componentNodeList) {
@DottedClassName String componentKindname = componentNode.valueOf("@componentKind");
if (componentKindname == null) {
throw new PluginException("Missing @componentKind for " + plugin.getPluginId()
+ " loaded from " + loadedFrom);
}
@DottedClassName String componentClassname = componentNode.valueOf("@componentClass");
if (componentClassname == null) {
throw new PluginException("Missing @componentClassname for " + plugin.getPluginId()
+ " loaded from " + loadedFrom);
}
String componentId = componentNode.valueOf("@id");
if (componentId == null) {
throw new PluginException("Missing @id for " + plugin.getPluginId()
+ " loaded from " + loadedFrom);
}
try {
String propertiesLocation = componentNode.valueOf("@properties");
boolean disabled = Boolean.valueOf(componentNode.valueOf("@disabled"));
Node filterMessageNode = findMessageNode(messageCollectionList,
"/MessageCollection/PluginComponent[@id='" + componentId + "']",
"Missing Cloud description for PluginComponent " + componentId);
String description = getChildText(filterMessageNode, "Description").trim();
String details = getChildText(filterMessageNode, "Details").trim();
PropertyBundle properties = new PropertyBundle();
if (propertiesLocation != null && propertiesLocation.length() > 0) {
URL properiesURL = classLoaderForResources.getResource(propertiesLocation);
if (properiesURL == null) {
AnalysisContext.logError("Could not load properties for " + plugin.getPluginId() + " component " + componentId
+ " from " + propertiesLocation);
continue;
}
properties.loadPropertiesFromURL(properiesURL);
}
List<Node> propertyNodes = XMLUtil.selectNodes(componentNode, "Property");
for (Node node : propertyNodes) {
String key = node.valueOf("@key");
String value = node.getText();
properties.setProperty(key, value);
}
Class<?> componentKind = classLoader.loadClass(componentKindname);
loadComponentPlugin(plugin, componentKind, componentClassname, componentId, disabled, description, details,
properties);
} catch (RuntimeException e) {
AnalysisContext.logError("Unable to load ComponentPlugin " + componentId +
" : " + componentClassname + " implementing " + componentKindname, e);
}
}
// Create FindBugsMains
if (!FindBugs.isNoMains()) {
List<Node> findBugsMainList = XMLUtil.selectNodes(pluginDescriptor, "/FindbugsPlugin/FindBugsMain");
for (Node main : findBugsMainList) {
String className = main.valueOf("@class");
if (className == null) {
throw new PluginException("Missing @class for FindBugsMain in plugin" + plugin.getPluginId()
+ " loaded from " + loadedFrom);
}
String cmd = main.valueOf("@cmd");
if (cmd == null) {
throw new PluginException("Missing @cmd for for FindBugsMain in plugin " + plugin.getPluginId()
+ " loaded from " + loadedFrom);
}
String kind = main.valueOf("@kind");
boolean analysis = Boolean.valueOf(main.valueOf("@analysis"));
Element mainMessageNode = (Element) findMessageNode(messageCollectionList,
"/MessageCollection/FindBugsMain[@cmd='" + cmd
// + " and @class='" + className
+"']/Description",
"Missing FindBugsMain description for cmd " + cmd);
String description = mainMessageNode.getTextTrim();
try {
Class<?> mainClass = classLoader.loadClass(className);
plugin.addFindBugsMain(mainClass, cmd, description, kind, analysis);
} catch (Exception e) {
String msg = "Unable to load FindBugsMain " + cmd +
" : " + className + " in plugin " + plugin.getPluginId()
+ " loaded from " + loadedFrom;
PluginException e2 = new PluginException(msg, e);
AnalysisContext.logError(msg, e2);
}
}
}
List<Node> detectorNodeList = XMLUtil.selectNodes(pluginDescriptor, "/FindbugsPlugin/Detector");
int detectorCount = 0;
for (Node detectorNode : detectorNodeList) {
String className = detectorNode.valueOf("@class");
String speed = detectorNode.valueOf("@speed");
String disabled = detectorNode.valueOf("@disabled");
String reports = detectorNode.valueOf("@reports");
String requireJRE = detectorNode.valueOf("@requirejre");
String hidden = detectorNode.valueOf("@hidden");
if (speed == null || speed.length() == 0) {
speed = "fast";
}
// System.out.println("Found detector: class="+className+", disabled="+disabled);
// Create DetectorFactory for the detector
Class<?> detectorClass = null;
if (!FindBugs.isNoAnalysis()) {
detectorClass = classLoader.loadClass(className);
if (!Detector.class.isAssignableFrom(detectorClass) && !Detector2.class.isAssignableFrom(detectorClass)) {
throw new PluginException("Class " + className + " does not implement Detector or Detector2");
}
}
DetectorFactory factory = new DetectorFactory(plugin, className, detectorClass, !disabled.equals("true"), speed,
reports, requireJRE);
if (Boolean.valueOf(hidden).booleanValue()) {
factory.setHidden(true);
}
factory.setPositionSpecifiedInPluginDescriptor(detectorCount++);
plugin.addDetectorFactory(factory);
// Find Detector node in one of the messages files,
// to get the detail HTML.
Node node = findMessageNode(messageCollectionList, "/MessageCollection/Detector[@class='" + className
+ "']/Details", "Missing Detector description for detector " + className);
Element details = (Element) node;
String detailHTML = details.getText();
StringBuilder buf = new StringBuilder();
buf.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
buf.append("<HTML><HEAD><TITLE>Detector Description</TITLE></HEAD><BODY>\n");
buf.append(detailHTML);
buf.append("</BODY></HTML>\n");
factory.setDetailHTML(buf.toString());
}
} catch (ClassNotFoundException e) {
throw new PluginException("Could not instantiate detector class: " + e, e);
}
// Create ordering constraints
Node orderingConstraintsNode = pluginDescriptor.selectSingleNode("/FindbugsPlugin/OrderingConstraints");
if (orderingConstraintsNode != null) {
// Get inter-pass and intra-pass constraints
List<Element> elements = XMLUtil.selectNodes(orderingConstraintsNode, "./SplitPass|./WithinPass");
for (Element constraintElement : elements) {
// Create the selectors which determine which detectors are
// involved in the constraint
DetectorFactorySelector earlierSelector = getConstraintSelector(constraintElement, plugin, "Earlier");
DetectorFactorySelector laterSelector = getConstraintSelector(constraintElement, plugin, "Later");
// Create the constraint
DetectorOrderingConstraint constraint = new DetectorOrderingConstraint(earlierSelector, laterSelector);
// Keep track of which constraints are single-source
constraint.setSingleSource(earlierSelector instanceof SingleDetectorFactorySelector);
// Add the constraint to the plugin
if (constraintElement.getName().equals("SplitPass")) {
plugin.addInterPassOrderingConstraint(constraint);
} else {
plugin.addIntraPassOrderingConstraint(constraint);
}
}
}
// register global Category descriptions
List<Node> categoryNodeListGlobal = XMLUtil.selectNodes(pluginDescriptor, "/FindbugsPlugin/BugCategory");
for(Node categoryNode : categoryNodeListGlobal) {
String key = categoryNode.valueOf("@category");
if (key.equals("")) {
throw new PluginException("BugCategory element with missing category attribute");
}
BugCategory bc = plugin.addOrCreateBugCategory(key);
boolean hidden = Boolean.valueOf(categoryNode.valueOf("@hidden"));
if (hidden) {
bc.setHidden(hidden);
}
}
for (Document messageCollection : messageCollectionList) {
List<Node> categoryNodeList = XMLUtil.selectNodes(messageCollection, "/MessageCollection/BugCategory");
if (DEBUG) {
System.out.println("found " + categoryNodeList.size() + " categories in " + plugin.getPluginId());
}
for (Node categoryNode : categoryNodeList) {
String key = categoryNode.valueOf("@category");
if (key.equals("")) {
throw new PluginException("BugCategory element with missing category attribute");
}
BugCategory bc = plugin.addOrCreateBugCategory(key);
String shortDesc = getChildText(categoryNode, "Description");
bc.setShortDescription(shortDesc);
try {
String abbrev = getChildText(categoryNode, "Abbreviation");
if (bc.getAbbrev() == null) {
bc.setAbbrev(abbrev);
if (DEBUG) {
System.out.println("category " + key + " abbrev -> " + abbrev);
}
} else if (DEBUG) {
System.out.println("rejected abbrev '" + abbrev + "' for category " + key + ": " + bc.getAbbrev());
}
} catch (PluginException pe) {
if (DEBUG)
{
System.out.println("missing Abbreviation for category " + key + "/" + shortDesc);
// do nothing else -- Abbreviation is required, but handle
// its omission gracefully
}
}
try {
String details = getChildText(categoryNode, "Details");
if (bc.getDetailText() == null) {
bc.setDetailText(details);
if (DEBUG) {
System.out.println("category " + key + " details -> " + details);
}
} else if (DEBUG) {
System.out.println("rejected details [" + details + "] for category " + key + ": [" + bc.getDetailText()
+ ']');
}
} catch (PluginException pe) {
// do nothing -- LongDescription is optional
}
}
}
// Create BugPatterns
List<Node> bugPatternNodeList = XMLUtil.selectNodes(pluginDescriptor, "/FindbugsPlugin/BugPattern");
for (Node bugPatternNode : bugPatternNodeList) {
String type = bugPatternNode.valueOf("@type");
String abbrev = bugPatternNode.valueOf("@abbrev");
String category = bugPatternNode.valueOf("@category");
String experimental = bugPatternNode.valueOf("@experimental");
// Find the matching element in messages.xml (or translations)
String query = "/MessageCollection/BugPattern[@type='" + type + "']";
Node messageNode = findMessageNode(messageCollectionList, query, "messages.xml missing BugPattern element for type "
+ type);
String shortDesc = getChildText(messageNode, "ShortDescription");
String longDesc = getChildText(messageNode, "LongDescription");
String detailText = getChildText(messageNode, "Details");
int cweid = 0;
try {
String cweString = bugPatternNode.valueOf("@cweid");
if (cweString.length() > 0) {
cweid = Integer.parseInt(cweString);
}
} catch (RuntimeException e) {
assert true; // ignore
}
BugPattern bugPattern = new BugPattern(type, abbrev, category, Boolean.valueOf(experimental).booleanValue(),
shortDesc, longDesc, detailText, cweid);
try {
String deprecatedStr = bugPatternNode.valueOf("@deprecated");
boolean deprecated = deprecatedStr.length() > 0 && Boolean.valueOf(deprecatedStr).booleanValue();
if (deprecated) {
bugPattern.setDeprecated(deprecated);
}
} catch (RuntimeException e) {
assert true; // ignore
}
plugin.addBugPattern(bugPattern);
}
// Create BugCodes
Set<String> definedBugCodes = new HashSet<String>();
for (Document messageCollection : messageCollectionList) {
List<Node> bugCodeNodeList = XMLUtil.selectNodes(messageCollection, "/MessageCollection/BugCode");
for (Node bugCodeNode : bugCodeNodeList) {
String abbrev = bugCodeNode.valueOf("@abbrev");
if (abbrev.equals("")) {
throw new PluginException("BugCode element with missing abbrev attribute");
}
if (definedBugCodes.contains(abbrev)) {
continue;
}
String description = bugCodeNode.getText();
String query = "/FindbugsPlugin/BugCode[@abbrev='" + abbrev + "']";
Node fbNode = pluginDescriptor.selectSingleNode(query);
int cweid = 0;
if (fbNode != null) {
try {
cweid = Integer.parseInt(fbNode.valueOf("@cweid"));
} catch (RuntimeException e) {
assert true; // ignore
}
}
BugCode bugCode = new BugCode(abbrev, description, cweid);
plugin.addBugCode(bugCode);
definedBugCodes.add(abbrev);
}
}
// If an engine registrar is specified, make a note of its classname
Node node = pluginDescriptor.selectSingleNode("/FindbugsPlugin/EngineRegistrar");
if (node != null) {
String engineClassName = node.valueOf("@class");
if (engineClassName == null) {
throw new PluginException("EngineRegistrar element with missing class attribute");
}
try {