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.util.ArrayDeque;
21 import java.util.Deque;
22 import org.xml.sax.Attributes;
23 import org.xml.sax.SAXException;
24 import org.xml.sax.helpers.DefaultHandler;
25
26 /**
27 * A handler to read the pom.xml model.
28 *
29 * @author Jeremy Long
30 */
31 public class PomHandler extends DefaultHandler {
32
33 /**
34 * The project element.
35 */
36 public static final String PROJECT = "project";
37 /**
38 * The artifactId element.
39 */
40 public static final String GROUPID = "groupId";
41 /**
42 * The artifactId element.
43 */
44 public static final String ARTIFACTID = "artifactId";
45 /**
46 * The version element.
47 */
48 public static final String VERSION = "version";
49 /**
50 * The parent element.
51 */
52 public static final String PARENT = "parent";
53 /**
54 * The name element.
55 */
56 public static final String NAME = "name";
57 /**
58 * The organization element.
59 */
60 public static final String ORGANIZATION = "organization";
61 /**
62 * The description element.
63 */
64 public static final String DESCRIPTION = "description";
65 /**
66 * The licenses element.
67 */
68 public static final String LICENSES = "licenses";
69 /**
70 * The license element.
71 */
72 public static final String LICENSE = "license";
73 /**
74 * The url element.
75 */
76 public static final String URL = "url";
77
78 /**
79 * The pom model.
80 */
81 private final Model model = new Model();
82
83 /**
84 * Returns the model obtained from the pom.xml.
85 *
86 * @return the model object
87 */
88 public Model getModel() {
89 return model;
90 }
91 /**
92 * The stack of elements processed; used to determine the parent node.
93 */
94 private final Deque<String> stack = new ArrayDeque<String>();
95 /**
96 * The license object.
97 */
98 private License license = null;
99
100 /**
101 * The current node text being extracted from the element.
102 */
103 private StringBuilder currentText;
104
105 /**
106 * Handles the start element event.
107 *
108 * @param uri the uri of the element being processed
109 * @param localName the local name of the element being processed
110 * @param qName the qName of the element being processed
111 * @param attributes the attributes of the element being processed
112 * @throws SAXException thrown if there is an exception processing
113 */
114 @Override
115 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
116 currentText = new StringBuilder();
117 stack.push(qName);
118 if (LICENSE.equals(qName)) {
119 license = new License();
120 }
121 }
122
123 /**
124 * Handles the end element event.
125 *
126 * @param uri the URI of the element
127 * @param localName the local name of the element
128 * @param qName the qName of the element
129 * @throws SAXException thrown if there is an exception processing
130 */
131 @Override
132 public void endElement(String uri, String localName, String qName) throws SAXException {
133 stack.pop();
134 final String parentNode = stack.peek();
135 if (PROJECT.equals(parentNode)) {
136 if (GROUPID.equals(qName)) {
137 model.setGroupId(currentText.toString());
138 } else if (ARTIFACTID.equals(qName)) {
139 model.setArtifactId(currentText.toString());
140 } else if (VERSION.equals(qName)) {
141 model.setVersion(currentText.toString());
142 } else if (NAME.equals(qName)) {
143 model.setName(currentText.toString());
144 } else if (ORGANIZATION.equals(qName)) {
145 model.setOrganization(currentText.toString());
146 } else if (DESCRIPTION.equals(qName)) {
147 model.setDescription(currentText.toString());
148 } else if (URL.equals(qName)) {
149 model.setProjectURL(currentText.toString());
150 }
151 } else if (PARENT.equals(parentNode)) {
152 if (GROUPID.equals(qName)) {
153 model.setParentGroupId(currentText.toString());
154 } else if (ARTIFACTID.equals(qName)) {
155 model.setParentArtifactId(currentText.toString());
156 } else if (VERSION.equals(qName)) {
157 model.setParentVersion(currentText.toString());
158 }
159 } else if (LICENSE.equals(parentNode)) {
160 if (license != null) {
161 if (NAME.equals(qName)) {
162 license.setName(currentText.toString());
163 } else if (URL.equals(qName)) {
164 license.setUrl(currentText.toString());
165 }
166 //} else {
167 //TODO add error logging
168 }
169 } else if (LICENSES.equals(parentNode)) {
170 if (LICENSE.equals(qName)) {
171 if (license != null) {
172 model.addLicense(license);
173 //} else {
174 //TODO add error logging
175 }
176 }
177 }
178 }
179
180 /**
181 * Collects the body text of the node being processed.
182 *
183 * @param ch the char array of text
184 * @param start the start position to copy text from in the char array
185 * @param length the number of characters to copy from the char array
186 * @throws SAXException thrown if there is a parsing exception
187 */
188 @Override
189 public void characters(char[] ch, int start, int length) throws SAXException {
190 currentText.append(ch, start, length);
191 }
192 }