• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 std::optional<ResourceId>& resid = {})
attributeAaptAttribute69       : attribute(attr), id(resid) {
70   }
71 
72   aapt::Attribute attribute;
73   std::optional<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   std::optional<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   void RemoveAttribute(const android::StringPiece& ns,
106                        const android::StringPiece& name);
107 
108   Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name);
109   const Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name) const;
110 
111   Element* FindChildWithAttribute(const android::StringPiece& ns, const android::StringPiece& name,
112                                   const android::StringPiece& attr_ns,
113                                   const android::StringPiece& attr_name,
114                                   const android::StringPiece& attr_value);
115 
116   const Element* FindChildWithAttribute(const android::StringPiece& ns,
117                                         const android::StringPiece& name,
118                                         const android::StringPiece& attr_ns,
119                                         const android::StringPiece& attr_name,
120                                         const android::StringPiece& attr_value) const;
121 
122   std::vector<Element*> GetChildElements();
123 
124   // Due to overriding of subtypes not working with unique_ptr, define a convenience Clone method
125   // that knows cloning an element returns an element.
126   std::unique_ptr<Element> CloneElement(const ElementCloneFunc& el_cloner) const;
127 
128   std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const override;
129 
130   void Accept(Visitor* visitor) override;
131   void Accept(ConstVisitor* visitor) const override;
132 };
133 
134 // A Text (CDATA) XML node. Can not have any children.
135 class Text : public Node {
136  public:
137   std::string text;
138 
139   std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const override;
140 
141   void Accept(Visitor* visitor) override;
142   void Accept(ConstVisitor* visitor) const override;
143 };
144 
145 // An XML resource with a source, name, and XML tree.
146 class XmlResource {
147  public:
148   ResourceFile file;
149 
150   // StringPool must come before the xml::Node. Destructors are called in reverse order, and
151   // the xml::Node may have StringPool references that need to be destroyed before the StringPool
152   // is destroyed.
153   StringPool string_pool;
154 
155   std::unique_ptr<xml::Element> root;
156 
157   std::unique_ptr<XmlResource> Clone() const;
158 };
159 
160 // Inflates an XML DOM from an InputStream, logging errors to the logger.
161 std::unique_ptr<XmlResource> Inflate(io::InputStream* in, IDiagnostics* diag, const Source& source);
162 
163 // Inflates an XML DOM from a binary ResXMLTree.
164 std::unique_ptr<XmlResource> Inflate(const void* data, size_t len,
165                                      std::string* out_error = nullptr);
166 
167 Element* FindRootElement(Node* node);
168 
169 // Visitor whose default implementation visits the children nodes of any node.
170 class Visitor {
171  public:
172   virtual ~Visitor() = default;
173 
Visit(Element * el)174   virtual void Visit(Element* el) {
175     VisitChildren(el);
176   }
177 
Visit(Text * text)178   virtual void Visit(Text* text) {
179   }
180 
181  protected:
182   Visitor() = default;
183 
VisitChildren(Element * el)184   void VisitChildren(Element* el) {
185     for (auto& child : el->children) {
186       child->Accept(this);
187     }
188   }
189 
BeforeVisitElement(Element * el)190   virtual void BeforeVisitElement(Element* el) {
191   }
AfterVisitElement(Element * el)192   virtual void AfterVisitElement(Element* el) {
193   }
194 
195  private:
196   DISALLOW_COPY_AND_ASSIGN(Visitor);
197 
198   friend class Element;
199 };
200 
201 class ConstVisitor {
202  public:
203   virtual ~ConstVisitor() = default;
204 
Visit(const Element * el)205   virtual void Visit(const Element* el) {
206     VisitChildren(el);
207   }
208 
Visit(const Text * text)209   virtual void Visit(const Text* text) {
210   }
211 
212  protected:
213   ConstVisitor() = default;
214 
VisitChildren(const Element * el)215   void VisitChildren(const Element* el) {
216     for (const auto& child : el->children) {
217       child->Accept(this);
218     }
219   }
220 
BeforeVisitElement(const Element * el)221   virtual void BeforeVisitElement(const Element* el) {
222   }
223 
AfterVisitElement(const Element * el)224   virtual void AfterVisitElement(const Element* el) {
225   }
226 
227  private:
228   DISALLOW_COPY_AND_ASSIGN(ConstVisitor);
229 
230   friend class Element;
231 };
232 
233 // An XML DOM visitor that will record the package name for a namespace prefix.
234 class PackageAwareVisitor : public Visitor, public IPackageDeclStack {
235  public:
236   using Visitor::Visit;
237 
238   std::optional<ExtractedPackage> TransformPackageAlias(
239       const android::StringPiece& alias) const override;
240 
241  protected:
242   PackageAwareVisitor() = default;
243 
244   void BeforeVisitElement(Element* el) override;
245   void AfterVisitElement(Element* el) override;
246 
247  private:
248   DISALLOW_COPY_AND_ASSIGN(PackageAwareVisitor);
249 
250   struct PackageDecl {
251     std::string prefix;
252     ExtractedPackage package;
253   };
254 
255   std::vector<std::vector<PackageDecl>> package_decls_;
256 };
257 
258 namespace internal {
259 
260 // Base class that overrides the default behaviour and does not descend into child nodes.
261 class NodeCastBase : public ConstVisitor {
262  public:
Visit(const Element * el)263   void Visit(const Element* el) override {
264   }
Visit(const Text * el)265   void Visit(const Text* el) override {
266   }
267 
268  protected:
269   NodeCastBase() = default;
270 
BeforeVisitElement(const Element * el)271   void BeforeVisitElement(const Element* el) override {
272   }
AfterVisitElement(const Element * el)273   void AfterVisitElement(const Element* el) override {
274   }
275 
276  private:
277   DISALLOW_COPY_AND_ASSIGN(NodeCastBase);
278 };
279 
280 template <typename T>
281 class NodeCastImpl : public NodeCastBase {
282  public:
283   using NodeCastBase::Visit;
284 
285   NodeCastImpl() = default;
286 
287   const T* value = nullptr;
288 
Visit(const T * v)289   void Visit(const T* v) override {
290     value = v;
291   }
292 
293  private:
294   DISALLOW_COPY_AND_ASSIGN(NodeCastImpl);
295 };
296 
297 }  // namespace internal
298 
299 template <typename T>
NodeCast(const Node * node)300 const T* NodeCast(const Node* node) {
301   internal::NodeCastImpl<T> visitor;
302   node->Accept(&visitor);
303   return visitor.value;
304 }
305 
306 template <typename T>
NodeCast(Node * node)307 T* NodeCast(Node* node) {
308   return const_cast<T*>(NodeCast<T>(static_cast<const T*>(node)));
309 }
310 
311 }  // namespace xml
312 }  // namespace aapt
313 
314 #endif  // AAPT_XML_DOM_H
315