1 /*
2 * Copyright (C) 2015 The Android Open Source Project
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
17 #ifndef AAPT_XML_DOM_H
18 #define AAPT_XML_DOM_H
19
20 #include <memory>
21 #include <string>
22 #include <vector>
23
24 #include "androidfw/StringPiece.h"
25
26 #include "Diagnostics.h"
27 #include "Resource.h"
28 #include "ResourceValues.h"
29 #include "io/Io.h"
30 #include "util/Util.h"
31 #include "xml/XmlUtil.h"
32
33 namespace aapt {
34 namespace xml {
35
36 class Element;
37 class Visitor;
38 class ConstVisitor;
39
40 // Base class for all XML nodes.
41 class Node {
42 public:
43 virtual ~Node() = default;
44
45 Element* parent = nullptr;
46 size_t line_number = 0u;
47 size_t column_number = 0u;
48 std::string comment;
49
50 virtual void Accept(Visitor* visitor) = 0;
51 virtual void Accept(ConstVisitor* visitor) const = 0;
52
53 using ElementCloneFunc = std::function<void(const Element&, Element*)>;
54
55 // Clones the Node subtree, using the given function to decide how to clone an Element.
56 virtual std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const = 0;
57 };
58
59 // A namespace declaration (xmlns:prefix="uri").
60 struct NamespaceDecl {
61 std::string prefix;
62 std::string uri;
63 size_t line_number = 0u;
64 size_t column_number = 0u;
65 };
66
67 struct AaptAttribute {
68 explicit AaptAttribute(const ::aapt::Attribute& attr, const Maybe<ResourceId>& resid = {})
attributeAaptAttribute69 : attribute(attr), id(resid) {
70 }
71
72 aapt::Attribute attribute;
73 Maybe<ResourceId> id;
74 };
75
76 // An XML attribute.
77 struct Attribute {
78 std::string namespace_uri;
79 std::string name;
80 std::string value;
81
82 Maybe<AaptAttribute> compiled_attribute;
83 std::unique_ptr<Item> compiled_value;
84 };
85
86 // An Element XML node.
87 class Element : public Node {
88 public:
89 // Ordered namespace prefix declarations.
90 std::vector<NamespaceDecl> namespace_decls;
91
92 std::string namespace_uri;
93 std::string name;
94 std::vector<Attribute> attributes;
95 std::vector<std::unique_ptr<Node>> children;
96
97 void AppendChild(std::unique_ptr<Node> child);
98 void InsertChild(size_t index, std::unique_ptr<Node> child);
99
100 Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name);
101 const Attribute* FindAttribute(const android::StringPiece& ns,
102 const android::StringPiece& name) const;
103 Attribute* FindOrCreateAttribute(const android::StringPiece& ns,
104 const android::StringPiece& name);
105
106 Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name);
107 const Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name) const;
108
109 Element* FindChildWithAttribute(const android::StringPiece& ns, const android::StringPiece& name,
110 const android::StringPiece& attr_ns,
111 const android::StringPiece& attr_name,
112 const android::StringPiece& attr_value);
113
114 const Element* FindChildWithAttribute(const android::StringPiece& ns,
115 const android::StringPiece& name,
116 const android::StringPiece& attr_ns,
117 const android::StringPiece& attr_name,
118 const android::StringPiece& attr_value) const;
119
120 std::vector<Element*> GetChildElements();
121
122 // Due to overriding of subtypes not working with unique_ptr, define a convenience Clone method
123 // that knows cloning an element returns an element.
124 std::unique_ptr<Element> CloneElement(const ElementCloneFunc& el_cloner) const;
125
126 std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const override;
127
128 void Accept(Visitor* visitor) override;
129 void Accept(ConstVisitor* visitor) const override;
130 };
131
132 // A Text (CDATA) XML node. Can not have any children.
133 class Text : public Node {
134 public:
135 std::string text;
136
137 std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const override;
138
139 void Accept(Visitor* visitor) override;
140 void Accept(ConstVisitor* visitor) const override;
141 };
142
143 // An XML resource with a source, name, and XML tree.
144 class XmlResource {
145 public:
146 ResourceFile file;
147
148 // StringPool must come before the xml::Node. Destructors are called in reverse order, and
149 // the xml::Node may have StringPool references that need to be destroyed before the StringPool
150 // is destroyed.
151 StringPool string_pool;
152
153 std::unique_ptr<xml::Element> root;
154
155 std::unique_ptr<XmlResource> Clone() const;
156 };
157
158 // Inflates an XML DOM from an InputStream, logging errors to the logger.
159 std::unique_ptr<XmlResource> Inflate(io::InputStream* in, IDiagnostics* diag, const Source& source);
160
161 // Inflates an XML DOM from a binary ResXMLTree.
162 std::unique_ptr<XmlResource> Inflate(const void* data, size_t len,
163 std::string* out_error = nullptr);
164
165 Element* FindRootElement(Node* node);
166
167 // Visitor whose default implementation visits the children nodes of any node.
168 class Visitor {
169 public:
170 virtual ~Visitor() = default;
171
Visit(Element * el)172 virtual void Visit(Element* el) {
173 VisitChildren(el);
174 }
175
Visit(Text * text)176 virtual void Visit(Text* text) {
177 }
178
179 protected:
180 Visitor() = default;
181
VisitChildren(Element * el)182 void VisitChildren(Element* el) {
183 for (auto& child : el->children) {
184 child->Accept(this);
185 }
186 }
187
BeforeVisitElement(Element * el)188 virtual void BeforeVisitElement(Element* el) {
189 }
AfterVisitElement(Element * el)190 virtual void AfterVisitElement(Element* el) {
191 }
192
193 private:
194 DISALLOW_COPY_AND_ASSIGN(Visitor);
195
196 friend class Element;
197 };
198
199 class ConstVisitor {
200 public:
201 virtual ~ConstVisitor() = default;
202
Visit(const Element * el)203 virtual void Visit(const Element* el) {
204 VisitChildren(el);
205 }
206
Visit(const Text * text)207 virtual void Visit(const Text* text) {
208 }
209
210 protected:
211 ConstVisitor() = default;
212
VisitChildren(const Element * el)213 void VisitChildren(const Element* el) {
214 for (const auto& child : el->children) {
215 child->Accept(this);
216 }
217 }
218
BeforeVisitElement(const Element * el)219 virtual void BeforeVisitElement(const Element* el) {
220 }
221
AfterVisitElement(const Element * el)222 virtual void AfterVisitElement(const Element* el) {
223 }
224
225 private:
226 DISALLOW_COPY_AND_ASSIGN(ConstVisitor);
227
228 friend class Element;
229 };
230
231 // An XML DOM visitor that will record the package name for a namespace prefix.
232 class PackageAwareVisitor : public Visitor, public IPackageDeclStack {
233 public:
234 using Visitor::Visit;
235
236 Maybe<ExtractedPackage> TransformPackageAlias(const android::StringPiece& alias) const override;
237
238 protected:
239 PackageAwareVisitor() = default;
240
241 void BeforeVisitElement(Element* el) override;
242 void AfterVisitElement(Element* el) override;
243
244 private:
245 DISALLOW_COPY_AND_ASSIGN(PackageAwareVisitor);
246
247 struct PackageDecl {
248 std::string prefix;
249 ExtractedPackage package;
250 };
251
252 std::vector<std::vector<PackageDecl>> package_decls_;
253 };
254
255 namespace internal {
256
257 // Base class that overrides the default behaviour and does not descend into child nodes.
258 class NodeCastBase : public ConstVisitor {
259 public:
Visit(const Element * el)260 void Visit(const Element* el) override {
261 }
Visit(const Text * el)262 void Visit(const Text* el) override {
263 }
264
265 protected:
266 NodeCastBase() = default;
267
BeforeVisitElement(const Element * el)268 void BeforeVisitElement(const Element* el) override {
269 }
AfterVisitElement(const Element * el)270 void AfterVisitElement(const Element* el) override {
271 }
272
273 private:
274 DISALLOW_COPY_AND_ASSIGN(NodeCastBase);
275 };
276
277 template <typename T>
278 class NodeCastImpl : public NodeCastBase {
279 public:
280 using NodeCastBase::Visit;
281
282 NodeCastImpl() = default;
283
284 const T* value = nullptr;
285
Visit(const T * v)286 void Visit(const T* v) override {
287 value = v;
288 }
289
290 private:
291 DISALLOW_COPY_AND_ASSIGN(NodeCastImpl);
292 };
293
294 } // namespace internal
295
296 template <typename T>
NodeCast(const Node * node)297 const T* NodeCast(const Node* node) {
298 internal::NodeCastImpl<T> visitor;
299 node->Accept(&visitor);
300 return visitor.value;
301 }
302
303 template <typename T>
NodeCast(Node * node)304 T* NodeCast(Node* node) {
305 return const_cast<T*>(NodeCast<T>(static_cast<const T*>(node)));
306 }
307
308 } // namespace xml
309 } // namespace aapt
310
311 #endif // AAPT_XML_DOM_H
312