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 "Diagnostics.h"
21 #include "Resource.h"
22 #include "ResourceValues.h"
23 #include "util/StringPiece.h"
24 #include "util/Util.h"
25 #include "xml/XmlUtil.h"
26
27 #include <istream>
28 #include <memory>
29 #include <string>
30 #include <vector>
31
32 namespace aapt {
33 namespace xml {
34
35 struct RawVisitor;
36
37 /**
38 * Base class for all XML nodes.
39 */
40 struct Node {
41 Node* parent = nullptr;
42 size_t lineNumber = 0;
43 size_t columnNumber = 0;
44 std::u16string comment;
45 std::vector<std::unique_ptr<Node>> children;
46
47 virtual ~Node() = default;
48
49 void addChild(std::unique_ptr<Node> child);
50 virtual void accept(RawVisitor* visitor) = 0;
51 };
52
53 /**
54 * Base class that implements the visitor methods for a
55 * subclass of Node.
56 */
57 template <typename Derived>
58 struct BaseNode : public Node {
59 virtual void accept(RawVisitor* visitor) override;
60 };
61
62 /**
63 * A Namespace XML node. Can only have one child.
64 */
65 struct Namespace : public BaseNode<Namespace> {
66 std::u16string namespacePrefix;
67 std::u16string namespaceUri;
68 };
69
70 struct AaptAttribute {
71 Maybe<ResourceId> id;
72 aapt::Attribute attribute;
73 };
74
75 /**
76 * An XML attribute.
77 */
78 struct Attribute {
79 std::u16string namespaceUri;
80 std::u16string name;
81 std::u16string value;
82
83 Maybe<AaptAttribute> compiledAttribute;
84 std::unique_ptr<Item> compiledValue;
85 };
86
87 /**
88 * An Element XML node.
89 */
90 struct Element : public BaseNode<Element> {
91 std::u16string namespaceUri;
92 std::u16string name;
93 std::vector<Attribute> attributes;
94
95 Attribute* findAttribute(const StringPiece16& ns, const StringPiece16& name);
96 xml::Element* findChild(const StringPiece16& ns, const StringPiece16& name);
97 xml::Element* findChildWithAttribute(const StringPiece16& ns, const StringPiece16& name,
98 const StringPiece16& attrNs,
99 const StringPiece16& attrName,
100 const StringPiece16& attrValue);
101 std::vector<xml::Element*> getChildElements();
102 };
103
104 /**
105 * A Text (CDATA) XML node. Can not have any children.
106 */
107 struct Text : public BaseNode<Text> {
108 std::u16string text;
109 };
110
111 /**
112 * An XML resource with a source, name, and XML tree.
113 */
114 struct XmlResource {
115 ResourceFile file;
116 std::unique_ptr<xml::Node> root;
117 };
118
119 /**
120 * Inflates an XML DOM from a text stream, logging errors to the logger.
121 * Returns the root node on success, or nullptr on failure.
122 */
123 std::unique_ptr<XmlResource> inflate(std::istream* in, IDiagnostics* diag, const Source& source);
124
125 /**
126 * Inflates an XML DOM from a binary ResXMLTree, logging errors to the logger.
127 * Returns the root node on success, or nullptr on failure.
128 */
129 std::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag,
130 const Source& source);
131
132 Element* findRootElement(XmlResource* doc);
133 Element* findRootElement(Node* node);
134
135 /**
136 * A visitor interface for the different XML Node subtypes. This will not traverse into
137 * children. Use Visitor for that.
138 */
139 struct RawVisitor {
140 virtual ~RawVisitor() = default;
141
visitRawVisitor142 virtual void visit(Namespace* node) {}
visitRawVisitor143 virtual void visit(Element* node) {}
visitRawVisitor144 virtual void visit(Text* text) {}
145 };
146
147 /**
148 * Visitor whose default implementation visits the children nodes of any node.
149 */
150 struct Visitor : public RawVisitor {
151 using RawVisitor::visit;
152
visitVisitor153 void visit(Namespace* node) override {
154 visitChildren(node);
155 }
156
visitVisitor157 void visit(Element* node) override {
158 visitChildren(node);
159 }
160
visitVisitor161 void visit(Text* text) override {
162 visitChildren(text);
163 }
164
visitChildrenVisitor165 void visitChildren(Node* node) {
166 for (auto& child : node->children) {
167 child->accept(this);
168 }
169 }
170 };
171
172 /**
173 * An XML DOM visitor that will record the package name for a namespace prefix.
174 */
175 class PackageAwareVisitor : public Visitor, public IPackageDeclStack {
176 private:
177 struct PackageDecl {
178 std::u16string prefix;
179 ExtractedPackage package;
180 };
181
182 std::vector<PackageDecl> mPackageDecls;
183
184 public:
185 using Visitor::visit;
186
187 void visit(Namespace* ns) override;
188 Maybe<ExtractedPackage> transformPackageAlias(
189 const StringPiece16& alias, const StringPiece16& localPackage) const override;
190 };
191
192 // Implementations
193
194 template <typename Derived>
accept(RawVisitor * visitor)195 void BaseNode<Derived>::accept(RawVisitor* visitor) {
196 visitor->visit(static_cast<Derived*>(this));
197 }
198
199 template <typename T>
200 struct NodeCastImpl : public RawVisitor {
201 using RawVisitor::visit;
202
203 T* value = nullptr;
204
visitNodeCastImpl205 void visit(T* v) override {
206 value = v;
207 }
208 };
209
210 template <typename T>
nodeCast(Node * node)211 T* nodeCast(Node* node) {
212 NodeCastImpl<T> visitor;
213 node->accept(&visitor);
214 return visitor.value;
215 }
216
217 } // namespace xml
218 } // namespace aapt
219
220 #endif // AAPT_XML_DOM_H
221