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

eu.rssw.antlr.database.DumpFileUtils Maven / Gradle / Ivy

/*
 * OpenEdge plugin for SonarQube
 * Copyright (c) 2015-2024 Riverside Software
 * contact AT riverside DASH software DOT fr
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
 */
package eu.rssw.antlr.database;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Files;
import java.nio.file.Path;

import org.antlr.v4.runtime.ANTLRErrorListener;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;

import eu.rssw.antlr.database.objects.DatabaseDescription;

public final class DumpFileUtils {

  private DumpFileUtils() {
    // Not instantiated
  }

  public static final ParseTree getDumpFileParseTree(Path path) throws IOException {
    return getDumpFileParseTree(Files.newInputStream(path), null);
  }

  /**
   * DF file encoding is stored at the end of the file. It's usually not expected that Sonar properties will hold the
   * right value.
   */
  public static final ParseTree getDumpFileParseTree(InputStream stream, Charset defaultCharset) throws IOException {
    // FileInputStream doesn't support mark for example, so we read the entire file in memory
    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    byte[] buffer = new byte[16384];
    for (int len = stream.read(buffer); len != -1; len = stream.read(buffer)) {
      outStream.write(buffer, 0, len);
    }
    ByteArrayInputStream buffdInput = new ByteArrayInputStream(outStream.toByteArray());
    if (defaultCharset == null)
      defaultCharset = Charset.defaultCharset();

    // Trying to read codepage from DF footer
    LineProcessor charsetReader = new DFCodePageProcessor(defaultCharset);
    try (Reader reader =  new InputStreamReader(buffdInput, defaultCharset);
        BufferedReader buff = new BufferedReader(reader)) {
      String str = buff.readLine();
      while (str != null) {
        charsetReader.processLine(str);
        str = buff.readLine();
      }
    }
    buffdInput.reset();
    return getDumpFileParseTree(new InputStreamReader(buffdInput, charsetReader.getResult()));
  }

  public static final ParseTree getDumpFileParseTree(Reader reader) throws IOException {
    ANTLRErrorListener listener = new DescriptiveErrorListener();
    DumpFileGrammarLexer lexer = new DumpFileGrammarLexer(CharStreams.fromReader(reader));
    lexer.removeErrorListeners();
    lexer.addErrorListener(listener);

    // Using SLL first proved not to be useful for the DF parser, so we directly parse with LL prediction mode
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    DumpFileGrammarParser parser = new DumpFileGrammarParser(tokens);
    parser.removeErrorListeners();
    parser.addErrorListener(listener);

    return parser.dump();
  }

  public static final DatabaseDescription getDatabaseDescription(Path path) throws IOException {
    return getDatabaseDescription(path, com.google.common.io.Files.getNameWithoutExtension(path.getFileName().toString()));
  }

  public static final DatabaseDescription getDatabaseDescription(Path path, String dbName) throws IOException {
    DumpFileVisitor visitor = new DumpFileVisitor(dbName);
    visitor.visit(getDumpFileParseTree(path));

    return visitor.getDatabase();
  }

  public static final DatabaseDescription getDatabaseDescription(InputStream stream, Charset cs, String dbName) throws IOException {
    DumpFileVisitor visitor = new DumpFileVisitor(dbName);
    visitor.visit(getDumpFileParseTree(stream, cs));

    return visitor.getDatabase();
  }

  private interface LineProcessor {
    T getResult();
    boolean processLine(String line);
  }

  private static class DFCodePageProcessor implements LineProcessor {
    private Charset charset = Charset.defaultCharset();

    public DFCodePageProcessor(Charset charset) {
      if (charset != null)
        this.charset = charset;
    }

    @Override
    public Charset getResult() {
      return charset;
    }

    @Override
    public boolean processLine(String line) {
      if (line.startsWith("cpstream=")) {
        try {
          charset = Charset.forName(line.substring(9));
        } catch (IllegalCharsetNameException | UnsupportedCharsetException uncaught) {
          // Undefined for example...
        }
        return false;
      }
      return true;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy