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 17ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "Source.h" 18ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "java/AnnotationProcessor.h" 196cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski#include "java/ClassDefinition.h" 20ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "java/ManifestClassGenerator.h" 21ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "util/Maybe.h" 22467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlDom.h" 23ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 24ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include <algorithm> 25ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 26ca5638fd85098c3d0a699492751043545f75553aAdam Lesinskinamespace aapt { 27ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 28ca5638fd85098c3d0a699492751043545f75553aAdam Lesinskistatic Maybe<StringPiece16> extractJavaIdentifier(IDiagnostics* diag, const Source& source, 29ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski const StringPiece16& value) { 30ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski const StringPiece16 sep = u"."; 31ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski auto iter = std::find_end(value.begin(), value.end(), sep.begin(), sep.end()); 32ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 33ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski StringPiece16 result; 34ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (iter != value.end()) { 35ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski result.assign(iter + sep.size(), value.end() - (iter + sep.size())); 36ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } else { 37ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski result = value; 38ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 39ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 40ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (result.empty()) { 41ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski diag->error(DiagMessage(source) << "empty symbol"); 42ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return {}; 43ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 44ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 45ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski iter = util::findNonAlphaNumericAndNotInSet(result, u"_"); 46ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (iter != result.end()) { 47ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski diag->error(DiagMessage(source) 48ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski << "invalid character '" << StringPiece16(iter, 1) 49ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski << "' in '" << result << "'"); 50ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return {}; 51ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 52ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 53ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (*result.begin() >= u'0' && *result.begin() <= u'9') { 54ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski diag->error(DiagMessage(source) << "symbol can not start with a digit"); 55ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return {}; 56ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 57ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 58ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return result; 59ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 60ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 616cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinskistatic bool writeSymbol(const Source& source, IDiagnostics* diag, xml::Element* el, 626cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski ClassDefinition* classDef) { 632ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name"); 64ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (!attr) { 65ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski diag->error(DiagMessage(source) << "<" << el->name << "> must define 'android:name'"); 66ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return false; 67ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 68ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 69ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski Maybe<StringPiece16> result = extractJavaIdentifier(diag, source.withLine(el->lineNumber), 70ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski attr->value); 71ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (!result) { 72ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return false; 73ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 74ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 756cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski std::unique_ptr<StringMember> stringMember = util::make_unique<StringMember>( 766cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski util::utf16ToUtf8(result.value()), util::utf16ToUtf8(attr->value)); 776cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski stringMember->getCommentBuilder()->appendComment(el->comment); 786cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski 796cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski classDef->addMember(std::move(stringMember)); 80ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return true; 81ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 82ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 836cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinskistd::unique_ptr<ClassDefinition> generateManifestClass(IDiagnostics* diag, xml::XmlResource* res) { 84ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski xml::Element* el = xml::findRootElement(res->root.get()); 85ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (!el) { 866cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski diag->error(DiagMessage(res->file.source) << "no root tag defined"); 876cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski return {}; 88ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 89ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 90ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (el->name != u"manifest" && !el->namespaceUri.empty()) { 91ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski diag->error(DiagMessage(res->file.source) << "no <manifest> root tag defined"); 926cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski return {}; 93ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 94ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 956cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski std::unique_ptr<ClassDefinition> permissionClass = 966cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski util::make_unique<ClassDefinition>("permission", ClassQualifier::Static, false); 976cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski std::unique_ptr<ClassDefinition> permissionGroupClass = 986cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski util::make_unique<ClassDefinition>("permission_group", ClassQualifier::Static, false); 99ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 100ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski bool error = false; 101ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 1026cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski std::vector<xml::Element*> children = el->getChildElements(); 103ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski for (xml::Element* childEl : children) { 1046cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski if (childEl->namespaceUri.empty()) { 1056cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski if (childEl->name == u"permission") { 1066cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski error |= !writeSymbol(res->file.source, diag, childEl, permissionClass.get()); 1076cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski } else if (childEl->name == u"permission-group") { 1086cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski error |= !writeSymbol(res->file.source, diag, childEl, permissionGroupClass.get()); 1096cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski } 110ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 111ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 112ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 1136cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski if (error) { 1146cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski return {}; 115ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 116ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 1176cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski std::unique_ptr<ClassDefinition> manifestClass = 1186cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski util::make_unique<ClassDefinition>("Manifest", ClassQualifier::None, false); 1196cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski manifestClass->addMember(std::move(permissionClass)); 1206cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski manifestClass->addMember(std::move(permissionGroupClass)); 1216cbfb1de493e42d937158ed57495c9656864ccbaAdam Lesinski return manifestClass; 122ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 123ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 124ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} // namespace aapt 125