Home | History | Annotate | Download | only in commandoutput
      1 /*
      2  * Copyright (C) 2012 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 package com.motorolamobility.preflighting.internal.commandoutput;
     17 
     18 import java.io.File;
     19 import java.io.OutputStream;
     20 import java.io.PrintStream;
     21 import java.util.List;
     22 import java.util.Map;
     23 
     24 import javax.xml.parsers.ParserConfigurationException;
     25 
     26 import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl;
     27 import org.eclipse.core.runtime.IStatus;
     28 import org.w3c.dom.Document;
     29 import org.w3c.dom.Element;
     30 
     31 import com.motorolamobility.preflighting.core.exception.PreflightingToolException;
     32 import com.motorolamobility.preflighting.core.logging.PreflightingLogger;
     33 import com.motorolamobility.preflighting.core.utils.XmlUtils;
     34 import com.motorolamobility.preflighting.core.validation.ApplicationValidationResult;
     35 import com.motorolamobility.preflighting.core.validation.Parameter;
     36 import com.motorolamobility.preflighting.core.validation.ValidationManagerConfiguration;
     37 import com.motorolamobility.preflighting.core.validation.ValidationResult;
     38 import com.motorolamobility.preflighting.core.validation.ValidationResultData;
     39 import com.motorolamobility.preflighting.core.validation.ValidationResultData.SEVERITY;
     40 import com.motorolamobility.preflighting.core.verbose.WarningLevelFilter;
     41 import com.motorolamobility.preflighting.i18n.PreflightingNLS;
     42 import com.motorolamobility.preflighting.internal.PreflightingPlugin;
     43 import com.motorolamobility.preflighting.output.AbstractOutputter;
     44 
     45 public class XmlOutputter extends AbstractOutputter
     46 {
     47 
     48     protected Document document = null;
     49 
     50     private static final String XML_TAG_APP_VALIDATOR = "AppValidator";
     51 
     52     private static final String XML_TAG_APPLICATION = "Application";
     53 
     54     private static final String XML_TAG_ERROR = "Error";
     55 
     56     private static final String XML_TAG_FATAL_ERROR = "FatalError";
     57 
     58     private static final String XML_TAG_WARNING = "Warning";
     59 
     60     private static final String XML_TAG_RESOURCE = "Resource";
     61 
     62     private static final String XML_TAG_LINE = "Line";
     63 
     64     private static final String XML_TAG_SUGGESTION = "Suggestion";
     65 
     66     private static final String XML_ATTRIBUTE_CHECKER_ID = "checker_id";
     67 
     68     private static final String XML_ATTRIBUTE_CONDITION_ID = "condition_id";
     69 
     70     private static final String XML_ATTRIBUTE_INFO_URL = "info_url";
     71 
     72     private static final String XML_ATTRIBUTE_PATH = "path";
     73 
     74     private static final String XML_ATTRIBUTE_APP_NAME = "app_name";
     75 
     76     private static final String XML_TAG_DESCRIPTION = "Description";
     77 
     78     private static final String XML_TAG_PREVIEW = "Preview";
     79 
     80     private static final String XML_ATTRIBUTE_APPVALIDATOR_VERSION = "version";
     81 
     82     private static final String XML_ATTRIBUTE_APPLICATION_VERSION = "app_version";
     83 
     84     private static final String XML_ATTRIBUTE_MOTODEV_LINK = "description_url";
     85 
     86     private static final String XML_CHECKER_STATUS_VALUE_FAIL = "Failed";
     87 
     88     private static final String XML_CHECKER_STATUS_VALUE_DISABLED = "Disabled";
     89 
     90     private static final String XML_CHECKER_STATUS_VALUE_OK = "Executed";
     91 
     92     private static final String XML_ATTRIBUTE_MESSAGE = "message";
     93 
     94     private static final String XML_ATTRIBUTE_STATUS = "status";
     95 
     96     private static final String XML_TAG_CHECKER_STATUS = "CheckerStatus";
     97 
     98     private static final String XML_TAG_EXECUTION_REPORT = "ExecutionReport";
     99 
    100     //TODO change tag name
    101     private static final String XML_TAG_APP_VALIDATOR_EXECUTION_REPORT = "ExecutionReport";
    102 
    103     private static final String XML_TAG_MESSAGES = "Messages";
    104 
    105     /**
    106      * Writes to file xml or text in the following format: <br>
    107      * &lt;type (Error/Warning/Info)&gt; &lt;number files involved (Java, XML)&gt; &lt;filePath1 (without OS specific characters)&gt;:&lt;linePath1&gt; ... &lt;filePathN&gt;:&lt;linePathN&gt;  &lt;description&gt;
    108      * @throws PreflightingToolException
    109      */
    110     @Override
    111     public void print(ApplicationValidationResult result, OutputStream stream,
    112             List<Parameter> parameters) throws PreflightingToolException
    113     {
    114         initializeParams(parameters);
    115 
    116         try
    117         {
    118             Element appValElem = createRootNode();
    119 
    120             Element applicationElem = document.createElement(XML_TAG_APPLICATION);
    121             applicationElem.setAttribute(XML_ATTRIBUTE_APP_NAME, getApplicationFile().getName());
    122             applicationElem.setAttribute(XML_ATTRIBUTE_APPLICATION_VERSION,
    123                     String.valueOf(result.getVersion()));
    124 
    125             generateCustomApplicationNodes(applicationElem, result, parameters);
    126             appValElem.appendChild(applicationElem);
    127 
    128             Element messagesElement = document.createElement(XML_TAG_MESSAGES);
    129             applicationElem.appendChild(messagesElement);
    130 
    131             //create result nodes and append them to document
    132             generateResultNodes(messagesElement, result.getResults());
    133 
    134             generateExecutionReport(applicationElem, result.getExecutionStatus());
    135 
    136             //create XML output
    137             XmlUtils.printXMLFormat(document);
    138         }
    139         catch (Exception e)
    140         {
    141             PreflightingLogger.error(getClass(), PreflightingNLS.TextOutputter_IOExceptionMessage
    142                     + e.getMessage());
    143             throw new PreflightingToolException(
    144                     PreflightingNLS.XMLOutputter_PrintResultsErrorMessage, e);
    145         }
    146     }
    147 
    148     /*
    149      * Generates the nodes for the result list
    150      */
    151     private void generateResultNodes(Element rootElement, List<ValidationResult> result)
    152     {
    153         for (ValidationResult checker : result)
    154         {
    155             for (ValidationResultData data : checker.getValidationResult())
    156             {
    157                 if (SEVERITY.OK.compareTo(data.getSeverity()) != 0)
    158                 {
    159                     Element issueElement = createIssueNode(data.getSeverity());
    160                     issueElement.setAttribute(XML_ATTRIBUTE_CHECKER_ID, checker.getCheckerId());
    161                     issueElement.setAttribute(XML_ATTRIBUTE_CONDITION_ID, data.getConditionID());
    162                     if (data.getInfoURL() != null)
    163                     {
    164                         issueElement.setAttribute(XML_ATTRIBUTE_INFO_URL, data.getInfoURL());
    165                     }
    166                     Element descriptionElement = createDescriptionNode(data.getIssueDescription());
    167                     issueElement.appendChild(descriptionElement);
    168 
    169                     for (File currentFile : data.getFileToIssueLines().keySet())
    170                     {
    171                         Element resourceElement =
    172                                 createResourceNode(currentFile,
    173                                         data.getFileToIssueLines().get(currentFile));
    174                         issueElement.appendChild(resourceElement);
    175                     }
    176 
    177                     if (WarningLevelFilter.printQuickFixSuggestions())
    178                     {
    179                         Element suggestionElement =
    180                                 createSuggestionNode(data.getQuickFixSuggestion());
    181                         issueElement.appendChild(suggestionElement);
    182                     }
    183 
    184                     if (data.getPreview() != null)
    185                     {
    186                         Element previewElement = createPreviewNode(data.getPreview());
    187                         issueElement.appendChild(previewElement);
    188                     }
    189 
    190                     rootElement.appendChild(issueElement);
    191                 }
    192             }
    193         }
    194     }
    195 
    196     /*
    197      * Generate the execution report node based on contents from executionStatus map
    198      */
    199     private void generateExecutionReport(Element appValElem, Map<String, IStatus> executionStatus)
    200     {
    201         Element executionReportElement = document.createElement(XML_TAG_EXECUTION_REPORT);
    202 
    203         for (String checkerId : executionStatus.keySet())
    204         {
    205             IStatus checkerStatus = executionStatus.get(checkerId);
    206             Element checkerStatusElement = document.createElement(XML_TAG_CHECKER_STATUS);
    207 
    208             checkerStatusElement.setAttribute(XML_ATTRIBUTE_CHECKER_ID, checkerId);
    209 
    210             //checker status equal INFO will be displayed as not executed
    211             String status;
    212             switch (checkerStatus.getSeverity())
    213             {
    214                 case IStatus.OK:
    215                     status = XML_CHECKER_STATUS_VALUE_OK;
    216                     break;
    217                 case IStatus.INFO:
    218                     status = XML_CHECKER_STATUS_VALUE_DISABLED;
    219                     break;
    220                 default: //failed
    221                     status = XML_CHECKER_STATUS_VALUE_FAIL;
    222                     break;
    223             }
    224 
    225             checkerStatusElement.setAttribute(XML_ATTRIBUTE_STATUS, status);
    226             checkerStatusElement.setAttribute(XML_ATTRIBUTE_MESSAGE, checkerStatus.getMessage());
    227 
    228             executionReportElement.appendChild(checkerStatusElement);
    229         }
    230 
    231         appValElem.appendChild(executionReportElement);
    232     }
    233 
    234     /*
    235      * ERROR, FATAL_ERROR or WARNING nodes
    236      */
    237     private Element createIssueNode(SEVERITY severity)
    238     {
    239         Element element = null;
    240 
    241         if (SEVERITY.ERROR.compareTo(severity) == 0)
    242         {
    243             element = document.createElement(XML_TAG_ERROR);
    244         }
    245         else if (SEVERITY.WARNING.compareTo(severity) == 0)
    246         {
    247             element = document.createElement(XML_TAG_WARNING);
    248         }
    249         else if (SEVERITY.FATAL.compareTo(severity) == 0)
    250         {
    251             element = document.createElement(XML_TAG_FATAL_ERROR);
    252         }
    253 
    254         return element;
    255     }
    256 
    257     /*
    258      * Issue description node
    259      */
    260     private Element createDescriptionNode(String description)
    261     {
    262         Element element = document.createElement(XML_TAG_DESCRIPTION);
    263 
    264         if (description != null)
    265         {
    266             element.setTextContent(description);
    267         }
    268 
    269         return element;
    270     }
    271 
    272     /**
    273      * Create resource node
    274      * @param currentFile (resource)
    275      * @param lines with errors in this resource
    276      * @return the resource node
    277      */
    278     private Element createResourceNode(File currentFile, List<Integer> lines)
    279     {
    280         Element resElement = document.createElement(XML_TAG_RESOURCE);
    281         resElement.setAttribute(XML_ATTRIBUTE_PATH, computeResourcePath(currentFile));
    282 
    283         for (Integer currentLine : lines)
    284         {
    285             Element lineElement = document.createElement(XML_TAG_LINE);
    286             lineElement.setTextContent(currentLine.toString());
    287             resElement.appendChild(lineElement);
    288         }
    289 
    290         return resElement;
    291     }
    292 
    293     /**
    294      * Create fix sugestion node
    295      * @param suggestion text
    296      * @return the sugestion node
    297      */
    298     private Element createSuggestionNode(String suggestion)
    299     {
    300         Element sugElement = document.createElement(XML_TAG_SUGGESTION);
    301         sugElement.setTextContent(suggestion);
    302 
    303         return sugElement;
    304     }
    305 
    306     /**
    307      * Create a Preview node with Validation preview
    308      * @param preview text
    309      * @return preview node
    310      */
    311     private Element createPreviewNode(String preview)
    312     {
    313         Element previewElement = document.createElement(XML_TAG_PREVIEW);
    314         previewElement.setTextContent(preview);
    315 
    316         return previewElement;
    317     }
    318 
    319     @Override
    320     public void printError(Exception exceptionThrown, PrintStream out)
    321     {
    322         try
    323         {
    324             Element appValElem = createRootNode();
    325             Element executionReportElement =
    326                     document.createElement(XML_TAG_APP_VALIDATOR_EXECUTION_REPORT);
    327             executionReportElement
    328                     .setAttribute(XML_ATTRIBUTE_STATUS, XML_CHECKER_STATUS_VALUE_FAIL);
    329             executionReportElement
    330                     .setAttribute(XML_ATTRIBUTE_MESSAGE, exceptionThrown.getMessage());
    331             appValElem.appendChild(executionReportElement);
    332 
    333             XmlUtils.printXMLFormat(document);
    334         }
    335         catch (Exception e)
    336         {
    337             PreflightingLogger.error(getClass(),
    338                     PreflightingNLS.XMLOutputter_PrintResultsErrorMessage + e.getMessage());
    339         }
    340     }
    341 
    342     //creates the document and its root node
    343     private Element createRootNode() throws ParserConfigurationException
    344     {
    345         document = DocumentBuilderFactoryImpl.newInstance().newDocumentBuilder().newDocument();
    346 
    347         Element appValElem = document.createElement(XML_TAG_APP_VALIDATOR);
    348         document.appendChild(appValElem);
    349         String appValidatorVersion = PreflightingPlugin.getInstance().getAppValidatorVersion();
    350         ValidationManagerConfiguration valManagerConfiguration =
    351                 ValidationManagerConfiguration.getInstance();
    352         String motodevLink =
    353                 valManagerConfiguration
    354                         .getProperty(ValidationManagerConfiguration.ConfigProperties.BASE_URL_PROPERTY
    355                                 .getName());
    356         appValElem.setAttribute(XML_ATTRIBUTE_APPVALIDATOR_VERSION, appValidatorVersion);
    357         appValElem.setAttribute(XML_ATTRIBUTE_MOTODEV_LINK, motodevLink);
    358 
    359         return appValElem;
    360     }
    361 
    362     protected void generateCustomApplicationNodes(Element applicationElem,
    363             ApplicationValidationResult result, List<Parameter> params)
    364     {
    365         //Do nothing.
    366     }
    367 }
    368