View Javadoc
1   /*
2    * This file is part of dependency-check-core.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Copyright (c) 2015 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.xml.pom;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.util.jar.JarFile;
23  import java.util.zip.ZipEntry;
24  import javax.annotation.concurrent.ThreadSafe;
25  import org.owasp.dependencycheck.analyzer.JarAnalyzer;
26  import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
27  import org.owasp.dependencycheck.dependency.Dependency;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  import org.xml.sax.SAXParseException;
31  
32  /**
33   *
34   * @author jeremy long
35   */
36  @ThreadSafe
37  public final class PomUtils {
38  
39      /**
40       * The logger.
41       */
42      private static final Logger LOGGER = LoggerFactory.getLogger(PomUtils.class);
43  
44      /**
45       * empty private constructor for utility class.
46       */
47      private PomUtils() {
48      }
49  
50      /**
51       * Reads in the specified POM and converts it to a Model.
52       *
53       * @param file the pom.xml file
54       * @return returns an object representation of the POM
55       * @throws AnalysisException is thrown if there is an exception extracting
56       * or parsing the POM {@link Model} object
57       */
58      public static Model readPom(File file) throws AnalysisException {
59          Model model = null;
60          final PomParser parser = new PomParser();
61          try {
62              model = parser.parse(file);
63          } catch (PomParseException ex) {
64              if (ex.getCause() instanceof SAXParseException) {
65                  try {
66                      model = parser.parseWithoutDocTypeCleanup(file);
67                  } catch (PomParseException ex1) {
68                      LOGGER.warn("Unable to parse pom '{}'", file.getPath());
69                      LOGGER.debug("", ex1);
70                      throw new AnalysisException(ex1);
71                  }
72              }
73              if (model == null) {
74                  LOGGER.warn("Unable to parse pom '{}'", file.getPath());
75                  LOGGER.debug("", ex);
76                  throw new AnalysisException(ex);
77              }
78          } catch (Throwable ex) {
79              LOGGER.warn("Unexpected error during parsing of the pom '{}'", file.getPath());
80              LOGGER.debug("", ex);
81              throw new AnalysisException(ex);
82          }
83          if (model == null) {
84              throw new AnalysisException(String.format("Unable to parse pom '%s'", file.getPath()));
85          }
86          return model;
87      }
88  
89      /**
90       * Retrieves the specified POM from a jar file and converts it to a Model.
91       *
92       * @param path the path to the pom.xml file within the jar file
93       * @param jar the jar file to extract the pom from
94       * @return returns an object representation of the POM
95       * @throws AnalysisException is thrown if there is an exception extracting
96       * or parsing the POM {@link Model} object
97       */
98      public static Model readPom(String path, JarFile jar) throws AnalysisException {
99          final ZipEntry entry = jar.getEntry(path);
100         final PomParser parser = new PomParser();
101         Model model = null;
102         if (entry != null) { //should never be null
103             //noinspection CaughtExceptionImmediatelyRethrown
104             try {
105                 model = parser.parse(jar.getInputStream(entry));
106             } catch (PomParseException ex) {
107                 if (ex.getCause() instanceof SAXParseException) {
108                     try {
109                         model = parser.parseWithoutDocTypeCleanup(jar.getInputStream(entry));
110                     } catch (PomParseException ex1) {
111                         LOGGER.warn("Unable to parse pom '{}' in jar '{}'", path, jar.getName());
112                         LOGGER.debug("", ex1);
113                         throw new AnalysisException(ex1);
114                     } catch (IOException ex1) {
115                         LOGGER.warn("Unable to parse pom '{}' in jar '{}' (IO Exception)", path, jar.getName());
116                         LOGGER.debug("", ex);
117                         throw new AnalysisException(ex);
118                     }
119                 }
120                 if (model != null) {
121                     LOGGER.warn("Unable to parse pom '{}' in jar '{}'", path, jar.getName());
122                     LOGGER.debug("", ex);
123                     throw new AnalysisException(ex);
124                 }
125             } catch (SecurityException ex) {
126                 LOGGER.warn("Unable to parse pom '{}' in jar '{}'; invalid signature", path, jar.getName());
127                 LOGGER.debug("", ex);
128                 throw new AnalysisException(ex);
129             } catch (IOException ex) {
130                 LOGGER.warn("Unable to parse pom '{}' in jar '{}' (IO Exception)", path, jar.getName());
131                 LOGGER.debug("", ex);
132                 throw new AnalysisException(ex);
133             } catch (Throwable ex) {
134                 LOGGER.warn("Unexpected error during parsing of the pom '{}' in jar '{}'", path, jar.getName());
135                 LOGGER.debug("", ex);
136                 throw new AnalysisException(ex);
137             }
138             if (model == null) {
139                 throw new AnalysisException(String.format("Unable to parse pom '%s/%s'", jar.getName(), path));
140             }
141         }
142         return model;
143     }
144 
145     /**
146      * Reads in the pom file and adds elements as evidence to the given
147      * dependency.
148      *
149      * @param dependency the dependency being analyzed
150      * @param pomFile the pom file to read
151      * @throws AnalysisException is thrown if there is an exception parsing the
152      * pom
153      */
154     public static void analyzePOM(Dependency dependency, File pomFile) throws AnalysisException {
155         final Model pom = PomUtils.readPom(pomFile);
156         JarAnalyzer.setPomEvidence(dependency, pom, null, true);
157     }
158 }