Home | History | Annotate | Download | only in xml
      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 = {})
     69       : 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 
    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 
    199 class 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.
    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:
    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 
    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 
    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>
    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>
    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