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