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 <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 
     33 namespace aapt {
     34 namespace xml {
     35 
     36 class RawVisitor;
     37 
     38 class Element;
     39 
     40 /**
     41  * Base class for all XML nodes.
     42  */
     43 class 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  */
     67 template <typename Derived>
     68 class 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  */
     76 class 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 
     84 struct 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  */
     96 struct 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  */
    108 class 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  */
    130 class 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  */
    140 class 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  */
    156 std::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  */
    162 std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag,
    163                                      const Source& source);
    164 
    165 Element* FindRootElement(XmlResource* doc);
    166 Element* 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  */
    173 class 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  */
    185 class 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  */
    205 class 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 
    224 template <typename Derived>
    225 void BaseNode<Derived>::Accept(RawVisitor* visitor) {
    226   visitor->Visit(static_cast<Derived*>(this));
    227 }
    228 
    229 template <typename T>
    230 class 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 
    239 template <typename T>
    240 T* 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