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 #include "xml/XmlUtil.h"
     18 
     19 #include <algorithm>
     20 #include <string>
     21 
     22 #include "util/Maybe.h"
     23 #include "util/Util.h"
     24 #include "xml/XmlDom.h"
     25 
     26 using ::android::StringPiece;
     27 
     28 namespace aapt {
     29 namespace xml {
     30 
     31 std::string BuildPackageNamespace(const StringPiece& package, bool private_reference) {
     32   std::string result = private_reference ? kSchemaPrivatePrefix : kSchemaPublicPrefix;
     33   result.append(package.data(), package.size());
     34   return result;
     35 }
     36 
     37 Maybe<ExtractedPackage> ExtractPackageFromNamespace(
     38     const std::string& namespace_uri) {
     39   if (util::StartsWith(namespace_uri, kSchemaPublicPrefix)) {
     40     StringPiece schema_prefix = kSchemaPublicPrefix;
     41     StringPiece package = namespace_uri;
     42     package = package.substr(schema_prefix.size(), package.size() - schema_prefix.size());
     43     if (package.empty()) {
     44       return {};
     45     }
     46     return ExtractedPackage{package.to_string(), false /* is_private */};
     47 
     48   } else if (util::StartsWith(namespace_uri, kSchemaPrivatePrefix)) {
     49     StringPiece schema_prefix = kSchemaPrivatePrefix;
     50     StringPiece package = namespace_uri;
     51     package = package.substr(schema_prefix.size(), package.size() - schema_prefix.size());
     52     if (package.empty()) {
     53       return {};
     54     }
     55     return ExtractedPackage{package.to_string(), true /* is_private */};
     56 
     57   } else if (namespace_uri == kSchemaAuto) {
     58     return ExtractedPackage{std::string(), true /* is_private */};
     59   }
     60   return {};
     61 }
     62 
     63 void ResolvePackage(const IPackageDeclStack* decl_stack, Reference* in_ref) {
     64   if (in_ref->name) {
     65     if (Maybe<ExtractedPackage> transformed_package =
     66             decl_stack->TransformPackageAlias(in_ref->name.value().package)) {
     67       ExtractedPackage& extracted_package = transformed_package.value();
     68       in_ref->name.value().package = std::move(extracted_package.package);
     69 
     70       // If the reference was already private (with a * prefix) and the
     71       // namespace is public, we keep the reference private.
     72       in_ref->private_reference |= extracted_package.private_namespace;
     73     }
     74   }
     75 }
     76 
     77 namespace {
     78 
     79 class ToolsNamespaceRemover : public Visitor {
     80  public:
     81   using Visitor::Visit;
     82 
     83   void Visit(Element* el) override {
     84     auto new_end =
     85         std::remove_if(el->namespace_decls.begin(), el->namespace_decls.end(),
     86                        [](const NamespaceDecl& decl) -> bool { return decl.uri == kSchemaTools; });
     87     el->namespace_decls.erase(new_end, el->namespace_decls.end());
     88 
     89     auto new_attr_end = std::remove_if(
     90         el->attributes.begin(), el->attributes.end(),
     91         [](const Attribute& attr) -> bool { return attr.namespace_uri == kSchemaTools; });
     92     el->attributes.erase(new_attr_end, el->attributes.end());
     93 
     94     Visitor::Visit(el);
     95   }
     96 };
     97 
     98 }  // namespace
     99 
    100 void StripAndroidStudioAttributes(Element* el) {
    101   ToolsNamespaceRemover remover;
    102   el->Accept(&remover);
    103 }
    104 
    105 }  // namespace xml
    106 }  // namespace aapt
    107