You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AbstractViolationsStaxParser.java 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. * Sonar, open source software quality management tool.
  3. * Copyright (C) 2009 SonarSource SA
  4. * mailto:contact AT sonarsource DOT com
  5. *
  6. * Sonar is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * Sonar is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with Sonar; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
  19. */
  20. package org.sonar.api.batch;
  21. import static org.apache.commons.lang.StringUtils.isNotBlank;
  22. import java.io.File;
  23. import java.io.FileInputStream;
  24. import java.io.FileNotFoundException;
  25. import java.io.InputStream;
  26. import java.text.ParseException;
  27. import javax.xml.stream.XMLStreamException;
  28. import org.apache.commons.io.IOUtils;
  29. import org.codehaus.staxmate.in.SMEvent;
  30. import org.codehaus.staxmate.in.SMHierarchicCursor;
  31. import org.codehaus.staxmate.in.SMInputCursor;
  32. import org.sonar.api.profiles.RulesProfile;
  33. import org.sonar.api.resources.Resource;
  34. import org.sonar.api.rules.Rule;
  35. import org.sonar.api.rules.RulesManager;
  36. import org.sonar.api.rules.Violation;
  37. import org.sonar.api.utils.ParsingUtils;
  38. import org.sonar.api.utils.StaxParser;
  39. /**
  40. * @since 1.10
  41. * @deprecated since 2.3. Too much "black-box".
  42. */
  43. @Deprecated
  44. public abstract class AbstractViolationsStaxParser {
  45. protected RulesManager rulesManager;
  46. protected SensorContext context;
  47. protected boolean doSaveViolationsOnUnexistedResource = true;
  48. /**
  49. * @deprecated since 1.11.
  50. */
  51. @Deprecated
  52. protected AbstractViolationsStaxParser(SensorContext context, RulesManager rulesManager, RulesProfile profile) {
  53. this.rulesManager = rulesManager;
  54. this.context = context;
  55. }
  56. protected AbstractViolationsStaxParser(SensorContext context, RulesManager rulesManager) {
  57. this.rulesManager = rulesManager;
  58. this.context = context;
  59. }
  60. /**
  61. * Cursor for child resources to parse, the returned input cursor should be filtered on SMEvent.START_ELEMENT for optimal perfs
  62. *
  63. * @param rootCursor
  64. * the root xml doc cursor
  65. * @return a cursor with child resources elements to parse
  66. */
  67. protected abstract SMInputCursor cursorForResources(SMInputCursor rootCursor) throws XMLStreamException;
  68. /**
  69. * Cursor for violations to parse for a given resource, the returned input cursor should be filtered on SMEvent.START_ELEMENT for optimal
  70. * perfs
  71. *
  72. * @param resourcesCursor
  73. * the current resource cursor
  74. * @return a cursor with child violations elements to parse
  75. */
  76. protected abstract SMInputCursor cursorForViolations(SMInputCursor resourcesCursor) throws XMLStreamException;
  77. /**
  78. * Transforms a given xml resource to a resource Object
  79. */
  80. protected abstract Resource toResource(SMInputCursor resourceCursor) throws XMLStreamException;
  81. protected abstract String messageFor(SMInputCursor violationCursor) throws XMLStreamException;
  82. protected abstract String ruleKey(SMInputCursor violationCursor) throws XMLStreamException;
  83. protected abstract String keyForPlugin();
  84. protected abstract String lineNumberForViolation(SMInputCursor violationCursor) throws XMLStreamException;
  85. /**
  86. * Specify if violations must be saved even if when the Resource associated to a violation doesn't yet exist.
  87. * In that case the Resource is automatically created.
  88. *
  89. * @param doSaveViolationsOnUnexistedResource by default, the value is true
  90. */
  91. public final void setDoSaveViolationsOnUnexistedResource(boolean doSaveViolationsOnUnexistedResource) {
  92. this.doSaveViolationsOnUnexistedResource = doSaveViolationsOnUnexistedResource;
  93. }
  94. public void parse(File violationsXMLFile) throws XMLStreamException {
  95. if (violationsXMLFile != null && violationsXMLFile.exists()) {
  96. InputStream input = null;
  97. try {
  98. input = new FileInputStream(violationsXMLFile);
  99. parse(input);
  100. } catch (FileNotFoundException e) {
  101. throw new XMLStreamException(e);
  102. } finally {
  103. IOUtils.closeQuietly(input);
  104. }
  105. }
  106. }
  107. public final void parse(InputStream input) throws XMLStreamException {
  108. if (input != null) {
  109. StaxParser parser = new StaxParser(new StaxParser.XmlStreamHandler() {
  110. public void stream(SMHierarchicCursor rootCursor) throws XMLStreamException {
  111. parseResources(rootCursor.advance());
  112. }
  113. }, true);
  114. parser.parse(input);
  115. }
  116. }
  117. private void parseResources(SMInputCursor rootCursor) throws XMLStreamException {
  118. SMInputCursor resourcesCursor = cursorForResources(rootCursor);
  119. SMEvent event;
  120. while ((event = resourcesCursor.getNext()) != null) {
  121. if (event.compareTo(SMEvent.START_ELEMENT) == 0) {
  122. parseViolations(resourcesCursor);
  123. }
  124. }
  125. }
  126. private void parseViolations(SMInputCursor resourcesCursor) throws XMLStreamException {
  127. Resource resource = toResource(resourcesCursor);
  128. if ( !doSaveViolationsOnUnexistedResource && context.getResource(resource) == null) {
  129. return;
  130. }
  131. SMInputCursor violationsCursor = cursorForViolations(resourcesCursor);
  132. SMEvent event;
  133. while ((event = violationsCursor.getNext()) != null) {
  134. if (event.compareTo(SMEvent.START_ELEMENT) == 0) {
  135. createViolationFor(resource, violationsCursor);
  136. }
  137. }
  138. }
  139. private void createViolationFor(Resource resource, SMInputCursor violationCursor) throws XMLStreamException {
  140. Rule rule = getRule(violationCursor);
  141. Integer line = getLineIndex(violationCursor);
  142. if (rule != null && resource != null) {
  143. Violation violation = Violation.create(rule, resource)
  144. .setLineId(line)
  145. .setMessage(messageFor(violationCursor));
  146. context.saveViolation(violation);
  147. }
  148. }
  149. private Rule getRule(SMInputCursor violationCursor) throws XMLStreamException {
  150. return rulesManager.getPluginRule(keyForPlugin(), ruleKey(violationCursor));
  151. }
  152. private Integer getLineIndex(SMInputCursor violationCursor) throws XMLStreamException {
  153. String line = lineNumberForViolation(violationCursor);
  154. return parseLineIndex(line);
  155. }
  156. protected static Integer parseLineIndex(String line) {
  157. if ( !isNotBlank(line) || line.indexOf('-') != -1) {
  158. return null;
  159. }
  160. try {
  161. return (int) ParsingUtils.parseNumber(line);
  162. } catch (ParseException ignore) {
  163. return null;
  164. }
  165. }
  166. }