io.codemodder.codemods.VerbTamperingCodemod Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core-codemods Show documentation
Show all versions of core-codemods Show documentation
Codemods for fixing common errors across many Java projects
package io.codemodder.codemods;
import io.codemodder.*;
import io.codemodder.codetf.CodeTFReference;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import javax.inject.Inject;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import org.dom4j.DocumentException;
import org.xml.sax.SAXException;
/** Removes all {@code } XML elements from files named web.xml. */
@Codemod(
id = "pixee:java/fix-verb-tampering",
importance = Importance.HIGH,
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW)
public final class VerbTamperingCodemod extends RawFileChanger {
private final XPathStreamProcessor processor;
@Inject
public VerbTamperingCodemod(final XPathStreamProcessor processor) {
this.processor = Objects.requireNonNull(processor);
}
@Override
public CodemodFileScanningResult visitFile(final CodemodInvocationContext context)
throws IOException {
Path file = context.path();
try {
List changes = processWebXml(context, file);
return CodemodFileScanningResult.withOnlyChanges(changes);
} catch (SAXException | DocumentException | XMLStreamException e) {
throw new IOException("Problem transforming web.xml", e);
}
}
private List processWebXml(final CodemodInvocationContext context, final Path file)
throws SAXException, IOException, DocumentException, XMLStreamException {
Optional change =
processor.process(
file, "//web-resource-collection/http-method", VerbTamperingCodemod::handle);
if (change.isEmpty()) {
return List.of();
}
XPathStreamProcessChange xmlChange = change.get();
Set linesAffected = xmlChange.linesAffected();
// add the weaves to the context
List changes = linesAffected.stream().map(CodemodChange::from).toList();
// overwrite the previous web.xml with the new one
Files.copy(xmlChange.transformedXml(), file, StandardCopyOption.REPLACE_EXISTING);
return changes;
}
/*
* Skip the events in the XML that constitute the {@code } element.
*/
private static void handle(
final XMLEventReader xmlEventReader,
final XMLEventWriter xmlEventWriter,
final XMLEvent currentEvent)
throws XMLStreamException {
// skip the text event
XMLEvent httpMethodEvent = xmlEventReader.nextEvent();
if (!httpMethodEvent.isCharacters()) {
throw new IllegalStateException("was expecting HTTP method");
}
// skip the end element event
XMLEvent endHttpMethodTag = xmlEventReader.nextEvent();
if (!endHttpMethodTag.isEndElement()) {
throw new IllegalStateException("was expecting end element");
}
}
@Override
public String getSummary() {
return reporter.getSummary();
}
@Override
public String getDescription() {
return reporter.getDescription();
}
@Override
public String getIndividualChangeDescription(final Path filePath, final CodemodChange change) {
return reporter.getChange(filePath, change);
}
@Override
public List getReferences() {
return reporter.getReferences().stream().map(u -> new CodeTFReference(u, u)).toList();
}
@Override
public IncludesExcludesPattern getIncludesExcludesPattern() {
return new IncludesExcludesPattern.Default(Set.of("{,**/}[wW][eE][bB].[xX][mM][lL]"), Set.of());
}
@Override
public boolean supports(final Path file) {
return "web.xml".equalsIgnoreCase(file.getFileName().toString());
}
}