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 <istream>
21#include <memory>
22#include <string>
23#include <vector>
24
25#include "androidfw/StringPiece.h"
26
27#include "Diagnostics.h"
28#include "Resource.h"
29#include "ResourceValues.h"
30#include "util/Util.h"
31#include "xml/XmlUtil.h"
32
33namespace aapt {
34namespace xml {
35
36class RawVisitor;
37
38class Element;
39
40/**
41 * Base class for all XML nodes.
42 */
43class Node {
44 public:
45  Node* parent = nullptr;
46  size_t line_number = 0;
47  size_t column_number = 0;
48  std::string comment;
49  std::vector<std::unique_ptr<Node>> children;
50
51  virtual ~Node() = default;
52
53  void AppendChild(std::unique_ptr<Node> child);
54  void InsertChild(size_t index, std::unique_ptr<Node> child);
55  virtual void Accept(RawVisitor* visitor) = 0;
56
57  using ElementCloneFunc = std::function<void(const Element&, Element*)>;
58
59  // Clones the Node subtree, using the given function to decide how to clone an Element.
60  virtual std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) = 0;
61};
62
63/**
64 * Base class that implements the visitor methods for a
65 * subclass of Node.
66 */
67template <typename Derived>
68class BaseNode : public Node {
69 public:
70  virtual void Accept(RawVisitor* visitor) override;
71};
72
73/**
74 * A Namespace XML node. Can only have one child.
75 */
76class Namespace : public BaseNode<Namespace> {
77 public:
78  std::string namespace_prefix;
79  std::string namespace_uri;
80
81  std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) override;
82};
83
84struct AaptAttribute {
85  explicit AaptAttribute(const ::aapt::Attribute& attr, const Maybe<ResourceId>& resid = {})
86      : attribute(attr), id(resid) {
87  }
88
89  aapt::Attribute attribute;
90  Maybe<ResourceId> id;
91};
92
93/**
94 * An XML attribute.
95 */
96struct Attribute {
97  std::string namespace_uri;
98  std::string name;
99  std::string value;
100
101  Maybe<AaptAttribute> compiled_attribute;
102  std::unique_ptr<Item> compiled_value;
103};
104
105/**
106 * An Element XML node.
107 */
108class Element : public BaseNode<Element> {
109 public:
110  std::string namespace_uri;
111  std::string name;
112  std::vector<Attribute> attributes;
113
114  Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name);
115  const Attribute* FindAttribute(const android::StringPiece& ns,
116                                 const android::StringPiece& name) const;
117  xml::Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name);
118  xml::Element* FindChildWithAttribute(const android::StringPiece& ns,
119                                       const android::StringPiece& name,
120                                       const android::StringPiece& attr_ns,
121                                       const android::StringPiece& attr_name,
122                                       const android::StringPiece& attr_value);
123  std::vector<xml::Element*> GetChildElements();
124  std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) override;
125};
126
127/**
128 * A Text (CDATA) XML node. Can not have any children.
129 */
130class Text : public BaseNode<Text> {
131 public:
132  std::string text;
133
134  std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) override;
135};
136
137/**
138 * An XML resource with a source, name, and XML tree.
139 */
140class XmlResource {
141 public:
142  ResourceFile file;
143
144  // StringPool must come before the xml::Node. Destructors are called in reverse order, and
145  // the xml::Node may have StringPool references that need to be destroyed before the StringPool
146  // is destroyed.
147  StringPool string_pool;
148
149  std::unique_ptr<xml::Node> root;
150};
151
152/**
153 * Inflates an XML DOM from a text stream, logging errors to the logger.
154 * Returns the root node on success, or nullptr on failure.
155 */
156std::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag, const Source& source);
157
158/**
159 * Inflates an XML DOM from a binary ResXMLTree, logging errors to the logger.
160 * Returns the root node on success, or nullptr on failure.
161 */
162std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag,
163                                     const Source& source);
164
165Element* FindRootElement(XmlResource* doc);
166Element* FindRootElement(Node* node);
167
168/**
169 * A visitor interface for the different XML Node subtypes. This will not
170 * traverse into
171 * children. Use Visitor for that.
172 */
173class RawVisitor {
174 public:
175  virtual ~RawVisitor() = default;
176
177  virtual void Visit(Namespace* node) {}
178  virtual void Visit(Element* node) {}
179  virtual void Visit(Text* text) {}
180};
181
182/**
183 * Visitor whose default implementation visits the children nodes of any node.
184 */
185class Visitor : public RawVisitor {
186 public:
187  using RawVisitor::Visit;
188
189  void Visit(Namespace* node) override { VisitChildren(node); }
190
191  void Visit(Element* node) override { VisitChildren(node); }
192
193  void Visit(Text* text) override { VisitChildren(text); }
194
195  void VisitChildren(Node* node) {
196    for (auto& child : node->children) {
197      child->Accept(this);
198    }
199  }
200};
201
202/**
203 * An XML DOM visitor that will record the package name for a namespace prefix.
204 */
205class PackageAwareVisitor : public Visitor, public IPackageDeclStack {
206 public:
207  using Visitor::Visit;
208
209  void Visit(Namespace* ns) override;
210  Maybe<ExtractedPackage> TransformPackageAlias(
211      const android::StringPiece& alias, const android::StringPiece& local_package) const override;
212
213 private:
214  struct PackageDecl {
215    std::string prefix;
216    ExtractedPackage package;
217  };
218
219  std::vector<PackageDecl> package_decls_;
220};
221
222// Implementations
223
224template <typename Derived>
225void BaseNode<Derived>::Accept(RawVisitor* visitor) {
226  visitor->Visit(static_cast<Derived*>(this));
227}
228
229template <typename T>
230class NodeCastImpl : public RawVisitor {
231 public:
232  using RawVisitor::Visit;
233
234  T* value = nullptr;
235
236  void Visit(T* v) override { value = v; }
237};
238
239template <typename T>
240T* NodeCast(Node* node) {
241  NodeCastImpl<T> visitor;
242  node->Accept(&visitor);
243  return visitor.value;
244}
245
246}  // namespace xml
247}  // namespace aapt
248
249#endif  // AAPT_XML_DOM_H
250