From d136aeda84f450529dc19328215729456b84ec1f Mon Sep 17 00:00:00 2001
From: Jeremy Long
Date: Wed, 18 Feb 2015 20:06:51 -0500
Subject: [PATCH] pom parsing was externalized so that it could be used in
multiple locations to assist in the resolution of issue #196
Former-commit-id: cbdde3b4b2dcabf0ff9e3f49cc3d36c62e67a1bb
---
.../dependencycheck/analyzer/JarAnalyzer.java | 149 +++++-------------
1 file changed, 36 insertions(+), 113 deletions(-)
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java
index c7fc30a0d..f17680cce 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java
@@ -61,6 +61,7 @@ import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.jaxb.pom.MavenNamespaceFilter;
+import org.owasp.dependencycheck.jaxb.pom.PomUtils;
import org.owasp.dependencycheck.jaxb.pom.generated.License;
import org.owasp.dependencycheck.jaxb.pom.generated.Model;
import org.owasp.dependencycheck.jaxb.pom.generated.Organization;
@@ -158,24 +159,15 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
* A pattern to detect HTML within text.
*/
private static final Pattern HTML_DETECTION_PATTERN = Pattern.compile("\\<[a-z]+.*/?\\>", Pattern.CASE_INSENSITIVE);
- /**
- * The unmarshaller used to parse the pom.xml from a JAR file.
- */
- private Unmarshaller pomUnmarshaller;
+
+ private PomUtils pomUtils = null;
//
/**
* Constructs a new JarAnalyzer.
*/
public JarAnalyzer() {
- try {
- //final JAXBContext jaxbContext = JAXBContext.newInstance("org.owasp.dependencycheck.jaxb.pom.generated");
- final JAXBContext jaxbContext = JAXBContext.newInstance(Model.class);
- pomUnmarshaller = jaxbContext.createUnmarshaller();
- } catch (JAXBException ex) { //guess we will just have a null pointer exception later...
- LOGGER.log(Level.SEVERE, "Unable to load parser. See the log for more details.");
- LOGGER.log(Level.FINE, null, ex);
- }
+ pomUtils = new PomUtils();
}
//
@@ -262,8 +254,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
- * Attempts to find a pom.xml within the JAR file. If found it extracts information and adds it to the evidence.
- * This will attempt to interpolate the strings contained within the pom.properties if one exists.
+ * Attempts to find a pom.xml within the JAR file. If found it extracts information and adds it to the evidence. This will
+ * attempt to interpolate the strings contained within the pom.properties if one exists.
*
* @param dependency the dependency being analyzed
* @param classes a collection of class name information
@@ -342,7 +334,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
if (externalPom == null) {
pom = retrievePom(path, jar);
} else {
- pom = retrievePom(externalPom);
+ pom = pomUtils.readPom(externalPom);
}
foundSomething |= setPomEvidence(dependency, pom, pomProperties, classes);
}
@@ -450,7 +442,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
final InputStreamReader reader = new InputStreamReader(fis, "UTF-8");
final InputSource xml = new InputSource(reader);
final SAXSource source = new SAXSource(xml);
- model = readPom(source);
+ model = pomUtils.readPom(source);
} catch (FileNotFoundException ex) {
final String msg = String.format("Unable to parse pom '%s' in jar '%s' (File Not Found)", path, jar.getName());
LOGGER.log(Level.WARNING, msg);
@@ -520,7 +512,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
final InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
final InputSource xml = new InputSource(reader);
final SAXSource source = new SAXSource(xml);
- model = readPom(source);
+ model = pomUtils.readPom(source);
} catch (SecurityException ex) {
final String msg = String.format("Unable to parse pom '%s' in jar '%s'; invalid signature", path, jar.getName());
LOGGER.log(Level.WARNING, msg);
@@ -541,81 +533,14 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
return model;
}
- /**
- * Reads in the specified POM and converts it to a Model.
- *
- * @param file the pom.xml file
- * @return returns a
- * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
- * {@link org.owasp.dependencycheck.jaxb.pom.generated.Model} object
- */
- private Model retrievePom(File file) throws AnalysisException {
- Model model = null;
- try {
- final FileInputStream stream = new FileInputStream(file);
- final InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
- final InputSource xml = new InputSource(reader);
- final SAXSource source = new SAXSource(xml);
- model = readPom(source);
- } catch (SecurityException ex) {
- final String msg = String.format("Unable to parse pom '%s'; invalid signature", file.getPath());
- LOGGER.log(Level.WARNING, msg);
- LOGGER.log(Level.FINE, null, ex);
- throw new AnalysisException(ex);
- } catch (IOException ex) {
- final String msg = String.format("Unable to parse pom '%s'(IO Exception)", file.getPath());
- LOGGER.log(Level.WARNING, msg);
- LOGGER.log(Level.FINE, "", ex);
- throw new AnalysisException(ex);
- } catch (Throwable ex) {
- final String msg = String.format("Unexpected error during parsing of the pom '%s'", file.getPath());
- LOGGER.log(Level.WARNING, msg);
- LOGGER.log(Level.FINE, "", ex);
- throw new AnalysisException(ex);
- }
- return model;
- }
-
- /**
- * Retrieves the specified POM from a jar file and converts it to a Model.
- *
- * @param source the SAXSource input stream to read the POM from
- * @return returns the POM object
- * @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
- * {@link org.owasp.dependencycheck.jaxb.pom.generated.Model} object
- */
- private Model readPom(SAXSource source) throws AnalysisException {
- Model model = null;
- try {
- final XMLFilter filter = new MavenNamespaceFilter();
- final SAXParserFactory spf = SAXParserFactory.newInstance();
- final SAXParser sp = spf.newSAXParser();
- final XMLReader xr = sp.getXMLReader();
- filter.setParent(xr);
- final JAXBElement el = pomUnmarshaller.unmarshal(source, Model.class);
- model = el.getValue();
- } catch (SecurityException ex) {
- throw new AnalysisException(ex);
- } catch (ParserConfigurationException ex) {
- throw new AnalysisException(ex);
- } catch (SAXException ex) {
- throw new AnalysisException(ex);
- } catch (JAXBException ex) {
- throw new AnalysisException(ex);
- } catch (Throwable ex) {
- throw new AnalysisException(ex);
- }
- return model;
- }
-
/**
* Sets evidence from the pom on the supplied dependency.
*
* @param dependency the dependency to set data on
* @param pom the information from the pom
* @param pomProperties the pom properties file (null if none exists)
- * @param classes a collection of ClassNameInformation - containing data about the fully qualified class names
- * within the JAR file being analyzed
+ * @param classes a collection of ClassNameInformation - containing data about the fully qualified class names within the JAR
+ * file being analyzed
* @return true if there was evidence within the pom that we could use; otherwise false
*/
private boolean setPomEvidence(Dependency dependency, Model pom, Properties pomProperties, ArrayList classes) {
@@ -739,8 +664,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
- * Analyzes the path information of the classes contained within the JarAnalyzer to try and determine possible
- * vendor or product names. If any are found they are stored in the packageVendor and packageProduct hashSets.
+ * Analyzes the path information of the classes contained within the JarAnalyzer to try and determine possible vendor or
+ * product names. If any are found they are stored in the packageVendor and packageProduct hashSets.
*
* @param classNames a list of class names
* @param dependency a dependency to analyze
@@ -948,18 +873,17 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
- * Adds a description to the given dependency. If the description contains one of the following strings beyond 100
- * characters, then the description used will be trimmed to that position:
+ * Adds a description to the given dependency. If the description contains one of the following strings beyond 100 characters,
+ * then the description used will be trimmed to that position:
* - "such as"
- "like "
- "will use "
- "* uses "
*
* @param dependency a dependency
* @param description the description
* @param source the source of the evidence
* @param key the "name" of the evidence
- * @return if the description is trimmed, the trimmed version is returned; otherwise the original description is
- * returned
+ * @return if the description is trimmed, the trimmed version is returned; otherwise the original description is returned
*/
- private String addDescription(Dependency dependency, String description, String source, String key) {
+ public static String addDescription(Dependency dependency, String description, String source, String key) {
if (dependency.getDescription() == null) {
dependency.setDescription(description);
}
@@ -1064,12 +988,11 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
/**
*
- * A utility function that will interpolate strings based on values given in the properties file. It will also
- * interpolate the strings contained within the properties file so that properties can reference other
- * properties.
+ * A utility function that will interpolate strings based on values given in the properties file. It will also interpolate the
+ * strings contained within the properties file so that properties can reference other properties.
*
- * Note: if there is no property found the reference will be removed. In other words, if the interpolated
- * string will be replaced with an empty string.
+ * Note: if there is no property found the reference will be removed. In other words, if the interpolated string will
+ * be replaced with an empty string.
*
*
* Example:
@@ -1089,13 +1012,13 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
* @param properties a collection of properties that may be referenced within the text.
* @return the interpolated text.
*/
- protected String interpolateString(String text, Properties properties) {
+ public static String interpolateString(String text, Properties properties) {
Properties props = properties;
if (text == null) {
return text;
}
if (props == null) {
- props = new Properties();
+ return text;
}
final int pos = text.indexOf("${");
@@ -1133,8 +1056,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
- * Cycles through an enumeration of JarEntries, contained within the dependency, and returns a list of the class
- * names. This does not include core Java package names (i.e. java.* or javax.*).
+ * Cycles through an enumeration of JarEntries, contained within the dependency, and returns a list of the class names. This
+ * does not include core Java package names (i.e. java.* or javax.*).
*
* @param dependency the dependency being analyzed
* @return an list of fully qualified class names
@@ -1171,8 +1094,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
- * Cycles through the list of class names and places the package levels 0-3 into the provided maps for vendor and
- * product. This is helpful when analyzing vendor/product as many times this is included in the package name.
+ * Cycles through the list of class names and places the package levels 0-3 into the provided maps for vendor and product.
+ * This is helpful when analyzing vendor/product as many times this is included in the package name.
*
* @param classNames a list of class names
* @param vendor HashMap of possible vendor names from package names (e.g. owasp)
@@ -1203,8 +1126,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
- * Adds an entry to the specified collection and sets the Integer (e.g. the count) to 1. If the entry already exists
- * in the collection then the Integer is incremented by 1.
+ * Adds an entry to the specified collection and sets the Integer (e.g. the count) to 1. If the entry already exists in the
+ * collection then the Integer is incremented by 1.
*
* @param collection a collection of strings and their occurrence count
* @param key the key to add to the collection
@@ -1218,9 +1141,9 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
- * Cycles through the collection of class name information to see if parts of the package names are contained in the
- * provided value. If found, it will be added as the HIGHEST confidence evidence because we have more then one
- * source corroborating the value.
+ * Cycles through the collection of class name information to see if parts of the package names are contained in the provided
+ * value. If found, it will be added as the HIGHEST confidence evidence because we have more then one source corroborating the
+ * value.
*
* @param classes a collection of class name information
* @param value the value to check to see if it contains a package name
@@ -1261,7 +1184,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
* @param pomProperties the properties, used for string interpolation
* @param dependency the dependency to add license information too
*/
- private void extractLicense(Model pom, Properties pomProperties, Dependency dependency) {
+ public static void extractLicense(Model pom, Properties pomProperties, Dependency dependency) {
//license
if (pom.getLicenses() != null) {
String license = null;
@@ -1302,9 +1225,9 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
/**
*
- * Stores information about a given class name. This class will keep the fully qualified class name and a list
- * of the important parts of the package structure. Up to the first four levels of the package structure are
- * stored, excluding a leading "org" or "com". Example:
+ * Stores information about a given class name. This class will keep the fully qualified class name and a list of the
+ * important parts of the package structure. Up to the first four levels of the package structure are stored, excluding a
+ * leading "org" or "com". Example:
* ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer");
* System.out.println(obj.getName());
* for (String p : obj.getPackageStructure())