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