ManifestClassGenerator.cpp revision ce5e56e243d262a9b65459c3bd0bb9eaadd40628
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 "java/ManifestClassGenerator.h" 18 19#include <algorithm> 20 21#include "Source.h" 22#include "java/AnnotationProcessor.h" 23#include "java/ClassDefinition.h" 24#include "util/Maybe.h" 25#include "xml/XmlDom.h" 26 27namespace aapt { 28 29static Maybe<StringPiece> ExtractJavaIdentifier(IDiagnostics* diag, 30 const Source& source, 31 const StringPiece& value) { 32 const StringPiece sep = "."; 33 auto iter = std::find_end(value.begin(), value.end(), sep.begin(), sep.end()); 34 35 StringPiece result; 36 if (iter != value.end()) { 37 result.assign(iter + sep.size(), value.end() - (iter + sep.size())); 38 } else { 39 result = value; 40 } 41 42 if (result.empty()) { 43 diag->Error(DiagMessage(source) << "empty symbol"); 44 return {}; 45 } 46 47 iter = util::FindNonAlphaNumericAndNotInSet(result, "_"); 48 if (iter != result.end()) { 49 diag->Error(DiagMessage(source) << "invalid character '" 50 << StringPiece(iter, 1) << "' in '" 51 << result << "'"); 52 return {}; 53 } 54 55 if (*result.begin() >= '0' && *result.begin() <= '9') { 56 diag->Error(DiagMessage(source) << "symbol can not start with a digit"); 57 return {}; 58 } 59 60 return result; 61} 62 63static bool WriteSymbol(const Source& source, IDiagnostics* diag, 64 xml::Element* el, ClassDefinition* class_def) { 65 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name"); 66 if (!attr) { 67 diag->Error(DiagMessage(source) << "<" << el->name 68 << "> must define 'android:name'"); 69 return false; 70 } 71 72 Maybe<StringPiece> result = ExtractJavaIdentifier( 73 diag, source.WithLine(el->line_number), attr->value); 74 if (!result) { 75 return false; 76 } 77 78 std::unique_ptr<StringMember> string_member = 79 util::make_unique<StringMember>(result.value(), attr->value); 80 string_member->GetCommentBuilder()->AppendComment(el->comment); 81 82 class_def->AddMember(std::move(string_member)); 83 return true; 84} 85 86std::unique_ptr<ClassDefinition> GenerateManifestClass(IDiagnostics* diag, 87 xml::XmlResource* res) { 88 xml::Element* el = xml::FindRootElement(res->root.get()); 89 if (!el) { 90 diag->Error(DiagMessage(res->file.source) << "no root tag defined"); 91 return {}; 92 } 93 94 if (el->name != "manifest" && !el->namespace_uri.empty()) { 95 diag->Error(DiagMessage(res->file.source) 96 << "no <manifest> root tag defined"); 97 return {}; 98 } 99 100 std::unique_ptr<ClassDefinition> permission_class = 101 util::make_unique<ClassDefinition>("permission", ClassQualifier::Static, 102 false); 103 std::unique_ptr<ClassDefinition> permission_group_class = 104 util::make_unique<ClassDefinition>("permission_group", 105 ClassQualifier::Static, false); 106 107 bool error = false; 108 std::vector<xml::Element*> children = el->GetChildElements(); 109 for (xml::Element* child_el : children) { 110 if (child_el->namespace_uri.empty()) { 111 if (child_el->name == "permission") { 112 error |= !WriteSymbol(res->file.source, diag, child_el, 113 permission_class.get()); 114 } else if (child_el->name == "permission-group") { 115 error |= !WriteSymbol(res->file.source, diag, child_el, 116 permission_group_class.get()); 117 } 118 } 119 } 120 121 if (error) { 122 return {}; 123 } 124 125 std::unique_ptr<ClassDefinition> manifest_class = 126 util::make_unique<ClassDefinition>("Manifest", ClassQualifier::None, 127 false); 128 manifest_class->AddMember(std::move(permission_class)); 129 manifest_class->AddMember(std::move(permission_group_class)); 130 return manifest_class; 131} 132 133} // namespace aapt 134