import com.google.common.collect.Iterables;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.SensorContext;
for (ClonePart part : duplication.getCloneParts()) {
xml.append("<b s=\"").append(part.getStartLine())
.append("\" l=\"").append(part.getLines())
- .append("\" r=\"").append(part.getResourceId())
+ .append("\" r=\"").append(StringEscapeUtils.escapeXml(part.getResourceId()))
.append("\"/>");
}
xml.append("</g>");
import org.junit.Test;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.resources.File;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.Resource;
import org.sonar.api.test.IsMeasure;
+ "</duplications>")));
}
+ @Test
+ public void shouldEscapeXmlEntities() {
+ File csharpFile = new File("Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs");
+ List<CloneGroup> groups = Arrays.asList(newCloneGroup(
+ new ClonePart("Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs", 0, 5, 204),
+ new ClonePart("Loads/File Loads/Subs & Reds/SubsRedsDelivery2.cs", 0, 15, 214)));
+ SonarEngine.save(context, csharpFile, groups);
+
+ verify(context).saveMeasure(
+ eq(csharpFile),
+ argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications><g>"
+ + "<b s=\"5\" l=\"200\" r=\"Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs\"/>"
+ + "<b s=\"15\" l=\"200\" r=\"Loads/File Loads/Subs & Reds/SubsRedsDelivery2.cs\"/>"
+ + "</g></duplications>")));
+ }
+
private CloneGroup newCloneGroup(ClonePart... parts) {
return CloneGroup.builder().setLength(0).setOrigin(parts[0]).setParts(Arrays.asList(parts)).build();
}