Home | History | Annotate | Download | only in xml
      1 /*
      2  * Copyright (C) 2016 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 "xml/XmlActionExecutor.h"
     18 
     19 namespace aapt {
     20 namespace xml {
     21 
     22 static bool wrapperOne(XmlNodeAction::ActionFunc& f, Element* el, SourcePathDiagnostics*) {
     23     return f(el);
     24 }
     25 
     26 static bool wrapperTwo(XmlNodeAction::ActionFuncWithDiag& f, Element* el,
     27                        SourcePathDiagnostics* diag) {
     28     return f(el, diag);
     29 }
     30 
     31 void XmlNodeAction::action(XmlNodeAction::ActionFunc f) {
     32     mActions.emplace_back(std::bind(wrapperOne, std::move(f),
     33                                     std::placeholders::_1,
     34                                     std::placeholders::_2));
     35 }
     36 
     37 void XmlNodeAction::action(XmlNodeAction::ActionFuncWithDiag f) {
     38     mActions.emplace_back(std::bind(wrapperTwo, std::move(f),
     39                                     std::placeholders::_1,
     40                                     std::placeholders::_2));
     41 }
     42 
     43 static void printElementToDiagMessage(const Element* el, DiagMessage* msg) {
     44     *msg << "<";
     45     if (!el->namespaceUri.empty()) {
     46         *msg << el->namespaceUri << ":";
     47     }
     48     *msg << el->name << ">";
     49 }
     50 
     51 bool XmlNodeAction::execute(XmlActionExecutorPolicy policy, SourcePathDiagnostics* diag,
     52                             Element* el) const {
     53     bool error = false;
     54     for (const ActionFuncWithDiag& action : mActions) {
     55         error |= !action(el, diag);
     56     }
     57 
     58     for (Element* childEl : el->getChildElements()) {
     59         if (childEl->namespaceUri.empty()) {
     60             std::map<std::u16string, XmlNodeAction>::const_iterator iter =
     61                     mMap.find(childEl->name);
     62             if (iter != mMap.end()) {
     63                 error |= !iter->second.execute(policy, diag, childEl);
     64                 continue;
     65             }
     66         }
     67 
     68         if (policy == XmlActionExecutorPolicy::Whitelist) {
     69             DiagMessage errorMsg(childEl->lineNumber);
     70             errorMsg << "unknown element ";
     71             printElementToDiagMessage(childEl, &errorMsg);
     72             errorMsg << " found";
     73             diag->error(errorMsg);
     74             error = true;
     75         }
     76     }
     77     return !error;
     78 }
     79 
     80 bool XmlActionExecutor::execute(XmlActionExecutorPolicy policy, IDiagnostics* diag,
     81                                 XmlResource* doc) const {
     82     SourcePathDiagnostics sourceDiag(doc->file.source, diag);
     83 
     84     Element* el = findRootElement(doc);
     85     if (!el) {
     86         if (policy == XmlActionExecutorPolicy::Whitelist) {
     87             sourceDiag.error(DiagMessage() << "no root XML tag found");
     88             return false;
     89         }
     90         return true;
     91     }
     92 
     93     if (el->namespaceUri.empty()) {
     94         std::map<std::u16string, XmlNodeAction>::const_iterator iter = mMap.find(el->name);
     95         if (iter != mMap.end()) {
     96             return iter->second.execute(policy, &sourceDiag, el);
     97         }
     98     }
     99 
    100     if (policy == XmlActionExecutorPolicy::Whitelist) {
    101         DiagMessage errorMsg(el->lineNumber);
    102         errorMsg << "unknown element ";
    103         printElementToDiagMessage(el, &errorMsg);
    104         errorMsg << " found";
    105         sourceDiag.error(errorMsg);
    106         return false;
    107     }
    108     return true;
    109 }
    110 
    111 } // namespace xml
    112 } // namespace aapt
    113