All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.ikor.sip.foundation.mvnplugin.ImportStatementParser Maven / Gradle / Ivy

The newest version!
package de.ikor.sip.foundation.mvnplugin;

import static java.lang.String.format;

import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.JavaSource;
import com.thoughtworks.qdox.model.impl.DefaultJavaClass;
import de.ikor.sip.foundation.mvnplugin.model.ImportStatement;
import de.ikor.sip.foundation.mvnplugin.model.ParsedJavaFile;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/** Parses a source file into a {@link ParsedJavaFile} representation. */
public final class ImportStatementParser {
  public static final String STATIC_PREFIX = "static ";
  private static final String IMPORT_PREFIX = "import ";
  private final LineReader lineReader;

  /**
   * Constructor just for testing purposes.
   *
   * @param charset used by te analysed project.
   */
  ImportStatementParser(Charset charset) {
    this.lineReader = new LineReader(charset);
  }

  /**
   * Converts files into more suitable {@link ParsedJavaFile} format.
   *
   * @param sourceFilePath path of the given file
   * @return instance of {@link ParsedJavaFile} containing encapsulated information of matter about
   *     the file.
   */
  public ParsedJavaFile parse(Path sourceFilePath) {
    try {
      JavaSource src = parseAsJavaSource(sourceFilePath);
      List importStatements = parseImportLines(sourceFilePath, src.getImports());
      String fullyQualifiedName = new DefaultJavaClass(src).getFullyQualifiedName();
      return new ParsedJavaFile(sourceFilePath, fullyQualifiedName, importStatements);
    } catch (IOException e) {
      throw new UncheckedIOException(
          format("Encountered IOException while analyzing %s for banned imports", sourceFilePath),
          e);
    }
  }

  private List parseImportLines(Path sourceFilePath, List importStrings)
      throws IOException {
    List imports = new LinkedList<>();
    try (final Stream lines = this.lineReader.lines(sourceFilePath).stream()) {
      int row = 1;
      for (final Iterator it = lines.map(String::trim).iterator(); it.hasNext(); ++row) {
        final String line = it.next();

        // Implementation note: We check for empty lines here
        // so that we are able to keep track of correct line numbers.
        if (line.isEmpty()) {
          continue;
        }
        if (importStrings.stream().anyMatch(line::contains)) {
          final List importStatements = parseImport(line, row);
          imports.addAll(importStatements);
        }
      }
      return imports;
    }
  }

  private JavaSource parseAsJavaSource(Path sourceFilePath) throws FileNotFoundException {
    JavaProjectBuilder builder = new JavaProjectBuilder();
    builder.addSource(new FileReader(sourceFilePath.toString()));
    return builder.getSources().stream()
        .findFirst()
        .orElseThrow(
            () -> new RuntimeException(format("qdox source parsing failed: %s", sourceFilePath)));
  }

  public List parseImport(String line, int lineNumber) {
    if (!isImport(line)) {
      return Collections.emptyList();
    }

    // There can be multiple import statements within the same line, so
    // we simply split them at their ';'
    final String[] parts = line.split(";");
    return Arrays.stream(parts)
        .map(String::trim)
        .filter(s -> !s.isEmpty())
        .map(s -> s.substring(IMPORT_PREFIX.length()))
        .map(importName -> toImportStatement(importName, lineNumber))
        .collect(Collectors.toList());
  }

  private ImportStatement toImportStatement(String importName, int lineNumber) {
    String trimmedImportName = importName.replace(STATIC_PREFIX, "").trim();
    boolean isStaticImport = importName.startsWith(STATIC_PREFIX);

    return new ImportStatement(trimmedImportName, lineNumber, isStaticImport);
  }

  private boolean isImport(String line) {
    return line.startsWith(IMPORT_PREFIX) && line.endsWith(";");
  }

  /**
   * Supplies lines but skips every encountered comment. Block comments that span multiple lines
   * will be replaced by the same amount of empty lines.
   */
  private static class LineReader {

    private final Charset charset;

    public LineReader(Charset charset) {
      this.charset = charset;
    }

    public Collection lines(Path path) throws IOException {
      final Reader fileReader = Files.newBufferedReader(path, charset);
      try (final BufferedReader lineReader = new BufferedReader(fileReader)) {
        return lineReader.lines().collect(Collectors.toList());
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy