View Javadoc
1   package org.codehaus.plexus.compiler.eclipse;
2   
3   import javax.xml.stream.XMLInputFactory;
4   import javax.xml.stream.XMLStreamConstants;
5   import javax.xml.stream.XMLStreamReader;
6   
7   import java.io.BufferedReader;
8   import java.io.File;
9   import java.io.FileInputStream;
10  import java.io.IOException;
11  import java.io.InputStreamReader;
12  import java.io.Reader;
13  import java.util.ArrayList;
14  import java.util.List;
15  
16  import org.codehaus.plexus.compiler.CompilerMessage;
17  import org.codehaus.plexus.compiler.CompilerMessage.Kind;
18  
19  /**
20   * @author <a href="mailto:jal@etc.to">Frits Jalvingh</a>
21   * Created on 31-3-18.
22   */
23  public class EcjResponseParser {
24      /*--------------------------------------------------------------*/
25      /*	CODING:	Decode ECJ -log format results.						*/
26      /*--------------------------------------------------------------*/
27  
28      private static final XMLInputFactory FACTORY = getStreamFactory();
29  
30      private static XMLInputFactory getStreamFactory() {
31          XMLInputFactory xmlif = XMLInputFactory.newInstance();
32          xmlif.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE);
33          xmlif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
34          xmlif.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
35          return xmlif;
36      }
37  
38      /**
39       * @param xmltf            the xml file
40       * @param errorsAsWarnings should we treat errors as warnings
41       *                         Scan the specified response file for compilation messages.
42       */
43      public List<CompilerMessage> parse(File xmltf, boolean errorsAsWarnings) throws Exception {
44          // if(xmltf.length() < 80)
45          //	return;
46  
47          List<CompilerMessage> list = new ArrayList<>();
48  
49          try (Reader src = new BufferedReader(new InputStreamReader(new FileInputStream(xmltf), "utf-8"))) {
50              XMLStreamReader xsr = FACTORY.createXMLStreamReader(src);
51  
52              // scan for "source" elements, skip all else.
53              while (xsr.hasNext()) {
54                  int type = xsr.next();
55                  if (type == XMLStreamConstants.START_ELEMENT && "source".equals(xsr.getLocalName())) {
56                      decodeSourceElement(list, xsr, errorsAsWarnings);
57                  }
58              }
59          }
60          return list;
61      }
62  
63      private void decodeSourceElement(List<CompilerMessage> list, XMLStreamReader xsr, boolean errorsAsWarnings)
64              throws Exception {
65          String filename = xsr.getAttributeValue(null, "path");
66  
67          // -- Got a file- call handler
68          File path = new File(filename).getCanonicalFile();
69          while (xsr.hasNext()) {
70              int type = xsr.nextTag();
71              if (type == XMLStreamConstants.START_ELEMENT) {
72                  if ("problems".equals(xsr.getLocalName())) {
73                      decodeProblems(list, path.toString(), xsr, errorsAsWarnings);
74                  } else {
75                      ignoreTillEnd(xsr);
76                  }
77              } else if (type == XMLStreamConstants.END_ELEMENT) {
78                  return;
79              }
80          }
81      }
82  
83      /**
84       * Locate "problem" nodes.
85       */
86      private void decodeProblems(
87              List<CompilerMessage> list, String sourcePath, XMLStreamReader xsr, boolean errorsAsWarnings)
88              throws Exception {
89          while (xsr.hasNext()) {
90              int type = xsr.nextTag();
91              if (type == XMLStreamConstants.START_ELEMENT) {
92                  if ("problem".equals(xsr.getLocalName())) {
93                      decodeProblem(list, sourcePath, xsr, errorsAsWarnings);
94                  } else {
95                      ignoreTillEnd(xsr);
96                  }
97  
98              } else if (type == XMLStreamConstants.END_ELEMENT) {
99                  return;
100             }
101         }
102     }
103 
104     private void decodeProblem(
105             List<CompilerMessage> list, String sourcePath, XMLStreamReader xsr, boolean errorsAsWarnings)
106             throws Exception {
107         String id = xsr.getAttributeValue(null, "optionKey"); // Key for the problem
108         int startline = getInt(xsr, "line");
109         int column = getInt(xsr, "charStart");
110         int endCol = getInt(xsr, "charEnd");
111         String sev = xsr.getAttributeValue(null, "severity");
112         String message = "Unknown message?";
113 
114         // -- Go watch for "message"
115         while (xsr.hasNext()) {
116             int type = xsr.nextTag();
117             if (type == XMLStreamConstants.START_ELEMENT) {
118                 if ("message".equals(xsr.getLocalName())) {
119                     message = xsr.getAttributeValue(null, "value");
120                 }
121                 ignoreTillEnd(xsr);
122 
123             } else if (type == XMLStreamConstants.END_ELEMENT) {
124                 break;
125             }
126         }
127 
128         Kind msgtype;
129         if ("warning".equalsIgnoreCase(sev)) {
130             msgtype = Kind.WARNING;
131         } else if ("error".equalsIgnoreCase(sev)) {
132             msgtype = errorsAsWarnings ? Kind.WARNING : Kind.ERROR;
133         } else if ("info".equalsIgnoreCase(sev)) {
134             msgtype = Kind.NOTE;
135         } else {
136             msgtype = Kind.OTHER;
137         }
138 
139         CompilerMessage cm = new CompilerMessage(sourcePath, msgtype, startline, column, startline, endCol, message);
140         list.add(cm);
141     }
142 
143     private static void ignoreTillEnd(XMLStreamReader xsr) throws Exception {
144         int depth = 1;
145         while (xsr.hasNext()) {
146             int type = xsr.next();
147             if (type == XMLStreamConstants.START_ELEMENT) {
148                 depth++;
149             } else if (type == XMLStreamConstants.END_ELEMENT) {
150                 depth--;
151                 if (depth == 0) {
152                     return;
153                 }
154             }
155         }
156     }
157 
158     private static int getInt(XMLStreamReader xsr, String name) throws IOException {
159         String v = xsr.getAttributeValue(null, name);
160         if (null == v) {
161             return -1;
162         }
163         try {
164             return Integer.parseInt(v.trim());
165         } catch (Exception x) {
166             throw new IOException("Illegal integer value '" + v + "' in attribute " + name);
167         }
168     }
169 }