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
33namespace aapt {
34namespace xml {
35
36class Element;
37class Visitor;
38class ConstVisitor;
39
40// Base class for all XML nodes.
41class 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").
60struct NamespaceDecl {
61  std::string prefix;
62  std::string uri;
63  size_t line_number = 0u;
64  size_t column_number = 0u;
65};
66
67struct AaptAttribute {
68  explicit AaptAttribute(const ::aapt::Attribute& attr, const Maybe<ResourceId>& resid = {})
69      : attribute(attr), id(resid) {
70  }
71
72  aapt::Attribute attribute;
73  Maybe<ResourceId> id;
74};
75
76// An XML attribute.
77struct 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.
87class 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.
133class 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.
144class 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.
159std::unique_ptr<XmlResource> Inflate(io::InputStream* in, IDiagnostics* diag, const Source& source);
160
161// Inflates an XML DOM from a binary ResXMLTree.
162std::unique_ptr<XmlResource> Inflate(const void* data, size_t len,
163                                     std::string* out_error = nullptr);
164
165Element* FindRootElement(Node* node);
166
167// Visitor whose default implementation visits the children nodes of any node.
168class Visitor {
169 public:
170  virtual ~Visitor() = default;
171
172  virtual void Visit(Element* el) {
173    VisitChildren(el);
174  }
175
176  virtual void Visit(Text* text) {
177  }
178
179 protected:
180  Visitor() = default;
181
182  void VisitChildren(Element* el) {
183    for (auto& child : el->children) {
184      child->Accept(this);
185    }
186  }
187
188  virtual void BeforeVisitElement(Element* el) {
189  }
190  virtual void AfterVisitElement(Element* el) {
191  }
192
193 private:
194  DISALLOW_COPY_AND_ASSIGN(Visitor);
195
196  friend class Element;
197};
198
199class ConstVisitor {
200 public:
201  virtual ~ConstVisitor() = default;
202
203  virtual void Visit(const Element* el) {
204    VisitChildren(el);
205  }
206
207  virtual void Visit(const Text* text) {
208  }
209
210 protected:
211  ConstVisitor() = default;
212
213  void VisitChildren(const Element* el) {
214    for (const auto& child : el->children) {
215      child->Accept(this);
216    }
217  }
218
219  virtual void BeforeVisitElement(const Element* el) {
220  }
221
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.
232class 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
255namespace internal {
256
257// Base class that overrides the default behaviour and does not descend into child nodes.
258class NodeCastBase : public ConstVisitor {
259 public:
260  void Visit(const Element* el) override {
261  }
262  void Visit(const Text* el) override {
263  }
264
265 protected:
266  NodeCastBase() = default;
267
268  void BeforeVisitElement(const Element* el) override {
269  }
270  void AfterVisitElement(const Element* el) override {
271  }
272
273 private:
274  DISALLOW_COPY_AND_ASSIGN(NodeCastBase);
275};
276
277template <typename T>
278class NodeCastImpl : public NodeCastBase {
279 public:
280  using NodeCastBase::Visit;
281
282  NodeCastImpl() = default;
283
284  const T* value = nullptr;
285
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
296template <typename T>
297const T* NodeCast(const Node* node) {
298  internal::NodeCastImpl<T> visitor;
299  node->Accept(&visitor);
300  return visitor.value;
301}
302
303template <typename T>
304T* 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