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 The OWASP Foundation. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.data.composer;
19  
20  import org.slf4j.Logger;
21  import org.slf4j.LoggerFactory;
22  
23  import javax.json.Json;
24  import javax.json.JsonArray;
25  import javax.json.JsonException;
26  import javax.json.JsonObject;
27  import javax.json.JsonReader;
28  import javax.json.stream.JsonParsingException;
29  import java.io.InputStream;
30  import java.util.ArrayList;
31  import java.util.List;
32  
33  /**
34   * Parses a Composer.lock file from an input stream. In a separate class so it can hopefully be injected.
35   *
36   * @author colezlaw
37   */
38  public class ComposerLockParser {
39  
40      /**
41       * The JsonReader for parsing JSON
42       */
43      private final JsonReader jsonReader;
44  
45      /**
46       * The input stream we'll read
47       */
48      private final InputStream inputStream; // NOPMD - it gets set in the constructor, read later
49  
50      /**
51       * The List of ComposerDependencies found
52       */
53      private final List<ComposerDependency> composerDependencies;
54  
55      /**
56       * The LOGGER
57       */
58      private static final Logger LOGGER = LoggerFactory.getLogger(ComposerLockParser.class);
59  
60      /**
61       * Createas a ComposerLockParser from a JsonReader and an InputStream.
62       *
63       * @param inputStream the InputStream to parse
64       */
65      public ComposerLockParser(InputStream inputStream) {
66          LOGGER.info("Creating a ComposerLockParser");
67          this.inputStream = inputStream;
68          this.jsonReader = Json.createReader(inputStream);
69          this.composerDependencies = new ArrayList<ComposerDependency>();
70      }
71  
72      /**
73       * Process the input stream to create the list of dependencies.
74       */
75      public void process() {
76          LOGGER.info("Beginning Composer lock processing");
77          try {
78              final JsonObject composer = jsonReader.readObject();
79              if (composer.containsKey("packages")) {
80                  LOGGER.debug("Found packages");
81                  final JsonArray packages = composer.getJsonArray("packages");
82                  for (JsonObject pkg : packages.getValuesAs(JsonObject.class)) {
83                      if (pkg.containsKey("name")) {
84                          final String groupName = pkg.getString("name");
85                          if (groupName.indexOf('/') >= 0 && groupName.indexOf('/') <= groupName.length() - 1) {
86                              if (pkg.containsKey("version")) {
87                                  final String group = groupName.substring(0, groupName.indexOf('/'));
88                                  final String project = groupName.substring(groupName.indexOf('/') + 1);
89                                  String version = pkg.getString("version");
90                                  // Some version nubmers begin with v - which doesn't end up matching CPE's
91                                  if (version.startsWith("v")) {
92                                      version = version.substring(1);
93                                  }
94                                  LOGGER.debug("Got package {}/{}/{}", group, project, version);
95                                  composerDependencies.add(new ComposerDependency(group, project, version));
96                              } else {
97                                  LOGGER.debug("Group/package {} does not have a version", groupName);
98                              }
99                          } else {
100                             LOGGER.debug("Got a dependency with no name");
101                         }
102                     }
103                 }
104             }
105         } catch (JsonParsingException jsonpe) {
106             throw new ComposerException("Error parsing stream", jsonpe);
107         } catch (JsonException jsone) {
108             throw new ComposerException("Error reading stream", jsone);
109         } catch (IllegalStateException ise) {
110             throw new ComposerException("Illegal state in composer stream", ise);
111         } catch (ClassCastException cce) {
112             throw new ComposerException("Not exactly composer lock", cce);
113         }
114     }
115 
116     /**
117      * Gets the list of dependencies.
118      *
119      * @return the list of dependencies
120      */
121     public List<ComposerDependency> getDependencies() {
122         return composerDependencies;
123     }
124 }