ManifestClassGenerator.cpp revision f852dd0eb86e461f1f039f6a292e62123757dad8
1ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski/* 2ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 3ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * 4ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * you may not use this file except in compliance with the License. 6ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * You may obtain a copy of the License at 7ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * 8ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * 10ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * Unless required by applicable law or agreed to in writing, software 11ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * See the License for the specific language governing permissions and 14ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski * limitations under the License. 15ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski */ 16ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 17ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "java/ManifestClassGenerator.h" 18ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 19ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <algorithm> 20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 21ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "Source.h" 22ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "java/AnnotationProcessor.h" 236cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski#include "java/ClassDefinition.h" 2409f4d706d9438980465faabe81ed143fc299343eAdam Lesinski#include "text/Unicode.h" 25ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "util/Maybe.h" 26467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlDom.h" 27ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 2809f4d706d9438980465faabe81ed143fc299343eAdam Lesinskiusing ::android::StringPiece; 2909f4d706d9438980465faabe81ed143fc299343eAdam Lesinskiusing ::aapt::text::IsJavaIdentifier; 30d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski 31ca5638fd85098c3d0a699492751043545f75553aAdam Lesinskinamespace aapt { 32ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 3309f4d706d9438980465faabe81ed143fc299343eAdam Lesinskistatic Maybe<StringPiece> ExtractJavaIdentifier(IDiagnostics* diag, const Source& source, 3409f4d706d9438980465faabe81ed143fc299343eAdam Lesinski const std::string& value) { 3509f4d706d9438980465faabe81ed143fc299343eAdam Lesinski StringPiece result = value; 3609f4d706d9438980465faabe81ed143fc299343eAdam Lesinski size_t pos = value.rfind('.'); 3709f4d706d9438980465faabe81ed143fc299343eAdam Lesinski if (pos != std::string::npos) { 3809f4d706d9438980465faabe81ed143fc299343eAdam Lesinski result = result.substr(pos + 1); 39ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 40ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 41ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (result.empty()) { 42ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(source) << "empty symbol"); 43ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 44ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 45ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 4609f4d706d9438980465faabe81ed143fc299343eAdam Lesinski if (!IsJavaIdentifier(result)) { 4709f4d706d9438980465faabe81ed143fc299343eAdam Lesinski diag->Error(DiagMessage(source) << "invalid Java identifier '" << result << "'"); 48ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 49ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return result; 51ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 52ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 5309f4d706d9438980465faabe81ed143fc299343eAdam Lesinskistatic bool WriteSymbol(const Source& source, IDiagnostics* diag, xml::Element* el, 5409f4d706d9438980465faabe81ed143fc299343eAdam Lesinski ClassDefinition* class_def) { 55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name"); 56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!attr) { 5709f4d706d9438980465faabe81ed143fc299343eAdam Lesinski diag->Error(DiagMessage(source) << "<" << el->name << "> must define 'android:name'"); 58ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return false; 59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 60ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 6109f4d706d9438980465faabe81ed143fc299343eAdam Lesinski Maybe<StringPiece> result = 6209f4d706d9438980465faabe81ed143fc299343eAdam Lesinski ExtractJavaIdentifier(diag, source.WithLine(el->line_number), attr->value); 63ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!result) { 64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return false; 65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 66ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 67ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<StringMember> string_member = 68ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski util::make_unique<StringMember>(result.value(), attr->value); 69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski string_member->GetCommentBuilder()->AppendComment(el->comment); 70ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 71f852dd0eb86e461f1f039f6a292e62123757dad8Adam Lesinski if (class_def->AddMember(std::move(string_member)) == ClassDefinition::Result::kOverridden) { 72f852dd0eb86e461f1f039f6a292e62123757dad8Adam Lesinski diag->Warn(DiagMessage(source.WithLine(el->line_number)) 73f852dd0eb86e461f1f039f6a292e62123757dad8Adam Lesinski << "duplicate definitions of '" << result.value() << "', overriding previous"); 74f852dd0eb86e461f1f039f6a292e62123757dad8Adam Lesinski } 75ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return true; 76ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 77ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 7809f4d706d9438980465faabe81ed143fc299343eAdam Lesinskistd::unique_ptr<ClassDefinition> GenerateManifestClass(IDiagnostics* diag, xml::XmlResource* res) { 79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::Element* el = xml::FindRootElement(res->root.get()); 80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!el) { 81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(res->file.source) << "no root tag defined"); 82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (el->name != "manifest" && !el->namespace_uri.empty()) { 8609f4d706d9438980465faabe81ed143fc299343eAdam Lesinski diag->Error(DiagMessage(res->file.source) << "no <manifest> root tag defined"); 87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<ClassDefinition> permission_class = 91ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski util::make_unique<ClassDefinition>("permission", ClassQualifier::kStatic, false); 92ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<ClassDefinition> permission_group_class = 93ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski util::make_unique<ClassDefinition>("permission_group", ClassQualifier::kStatic, false); 94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool error = false; 96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<xml::Element*> children = el->GetChildElements(); 97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (xml::Element* child_el : children) { 98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (child_el->namespace_uri.empty()) { 99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (child_el->name == "permission") { 10009f4d706d9438980465faabe81ed143fc299343eAdam Lesinski error |= !WriteSymbol(res->file.source, diag, child_el, permission_class.get()); 101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else if (child_el->name == "permission-group") { 10209f4d706d9438980465faabe81ed143fc299343eAdam Lesinski error |= !WriteSymbol(res->file.source, diag, child_el, permission_group_class.get()); 103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 104ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 105ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (error) { 108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 109ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 110ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<ClassDefinition> manifest_class = 112ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski util::make_unique<ClassDefinition>("Manifest", ClassQualifier::kNone, false); 113ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski manifest_class->AddMember(std::move(permission_class)); 114ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski manifest_class->AddMember(std::move(permission_group_class)); 115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return manifest_class; 116ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 117ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} // namespace aapt 119