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