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" 24d31bc123a06d2ffc2ca1b76a591a07865744ae12Izabela Orlowska#include "java/JavaClassGenerator.h" 2509f4d706d9438980465faabe81ed143fc299343eAdam Lesinski#include "text/Unicode.h" 26ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "util/Maybe.h" 27467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlDom.h" 28ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 2909f4d706d9438980465faabe81ed143fc299343eAdam Lesinskiusing ::android::StringPiece; 3009f4d706d9438980465faabe81ed143fc299343eAdam Lesinskiusing ::aapt::text::IsJavaIdentifier; 31d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski 32ca5638fd85098c3d0a699492751043545f75553aAdam Lesinskinamespace aapt { 33ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 3409f4d706d9438980465faabe81ed143fc299343eAdam Lesinskistatic Maybe<StringPiece> ExtractJavaIdentifier(IDiagnostics* diag, const Source& source, 3509f4d706d9438980465faabe81ed143fc299343eAdam Lesinski const std::string& value) { 3609f4d706d9438980465faabe81ed143fc299343eAdam Lesinski StringPiece result = value; 3709f4d706d9438980465faabe81ed143fc299343eAdam Lesinski size_t pos = value.rfind('.'); 3809f4d706d9438980465faabe81ed143fc299343eAdam Lesinski if (pos != std::string::npos) { 3909f4d706d9438980465faabe81ed143fc299343eAdam Lesinski result = result.substr(pos + 1); 40ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 41ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 42d31bc123a06d2ffc2ca1b76a591a07865744ae12Izabela Orlowska // Normalize only the java identifier, leave the original value unchanged. 43d31bc123a06d2ffc2ca1b76a591a07865744ae12Izabela Orlowska if (result.contains("-")) { 44d31bc123a06d2ffc2ca1b76a591a07865744ae12Izabela Orlowska result = JavaClassGenerator::TransformToFieldName(result); 45d31bc123a06d2ffc2ca1b76a591a07865744ae12Izabela Orlowska } 46d31bc123a06d2ffc2ca1b76a591a07865744ae12Izabela Orlowska 47ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (result.empty()) { 48ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(source) << "empty symbol"); 49ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 5209f4d706d9438980465faabe81ed143fc299343eAdam Lesinski if (!IsJavaIdentifier(result)) { 5309f4d706d9438980465faabe81ed143fc299343eAdam Lesinski diag->Error(DiagMessage(source) << "invalid Java identifier '" << result << "'"); 54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return result; 57ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 58ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 5909f4d706d9438980465faabe81ed143fc299343eAdam Lesinskistatic bool WriteSymbol(const Source& source, IDiagnostics* diag, xml::Element* el, 6009f4d706d9438980465faabe81ed143fc299343eAdam Lesinski ClassDefinition* class_def) { 61ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name"); 62ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!attr) { 6309f4d706d9438980465faabe81ed143fc299343eAdam Lesinski diag->Error(DiagMessage(source) << "<" << el->name << "> must define 'android:name'"); 64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return false; 65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 66ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 6709f4d706d9438980465faabe81ed143fc299343eAdam Lesinski Maybe<StringPiece> result = 6809f4d706d9438980465faabe81ed143fc299343eAdam Lesinski ExtractJavaIdentifier(diag, source.WithLine(el->line_number), attr->value); 69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!result) { 70ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return false; 71ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 73ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<StringMember> string_member = 74ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski util::make_unique<StringMember>(result.value(), attr->value); 75ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski string_member->GetCommentBuilder()->AppendComment(el->comment); 76ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 77f852dd0eb86e461f1f039f6a292e62123757dad8Adam Lesinski if (class_def->AddMember(std::move(string_member)) == ClassDefinition::Result::kOverridden) { 78f852dd0eb86e461f1f039f6a292e62123757dad8Adam Lesinski diag->Warn(DiagMessage(source.WithLine(el->line_number)) 79f852dd0eb86e461f1f039f6a292e62123757dad8Adam Lesinski << "duplicate definitions of '" << result.value() << "', overriding previous"); 80f852dd0eb86e461f1f039f6a292e62123757dad8Adam Lesinski } 81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return true; 82ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 83ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 8409f4d706d9438980465faabe81ed143fc299343eAdam Lesinskistd::unique_ptr<ClassDefinition> GenerateManifestClass(IDiagnostics* diag, xml::XmlResource* res) { 85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::Element* el = xml::FindRootElement(res->root.get()); 86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!el) { 87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(res->file.source) << "no root tag defined"); 88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (el->name != "manifest" && !el->namespace_uri.empty()) { 9209f4d706d9438980465faabe81ed143fc299343eAdam Lesinski diag->Error(DiagMessage(res->file.source) << "no <manifest> root tag defined"); 93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<ClassDefinition> permission_class = 97ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski util::make_unique<ClassDefinition>("permission", ClassQualifier::kStatic, false); 98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<ClassDefinition> permission_group_class = 99ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski util::make_unique<ClassDefinition>("permission_group", ClassQualifier::kStatic, false); 100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool error = false; 102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<xml::Element*> children = el->GetChildElements(); 103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (xml::Element* child_el : children) { 104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (child_el->namespace_uri.empty()) { 105ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (child_el->name == "permission") { 10609f4d706d9438980465faabe81ed143fc299343eAdam Lesinski error |= !WriteSymbol(res->file.source, diag, child_el, permission_class.get()); 107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else if (child_el->name == "permission-group") { 10809f4d706d9438980465faabe81ed143fc299343eAdam Lesinski error |= !WriteSymbol(res->file.source, diag, child_el, permission_group_class.get()); 109ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 110ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 113ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (error) { 114ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<ClassDefinition> manifest_class = 118ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski util::make_unique<ClassDefinition>("Manifest", ClassQualifier::kNone, false); 119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski manifest_class->AddMember(std::move(permission_class)); 120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski manifest_class->AddMember(std::move(permission_group_class)); 121ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return manifest_class; 122ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 123ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} // namespace aapt 125