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

schemacrawler.tools.integration.maven.SchemaCrawlerMojo Maven / Gradle / Ivy

/*
 *
 * SchemaCrawler Report - Apache Maven Plugin
 * http://www.schemacrawler.com
 * Copyright (c) 2011-2020, Sualeh Fatehi.
 *
 * This library 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
 * 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 library;
 * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 */
package schemacrawler.tools.integration.maven;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import static us.fatehi.utility.Utility.isBlank;
import schemacrawler.Main;
import schemacrawler.tools.command.text.schema.options.PortableType;

/** Generates a SchemaCrawler report of the database. */
@Mojo(name = "schemacrawler", requiresReports = true, threadSafe = true)
public class SchemaCrawlerMojo extends AbstractMavenReport {

  /**
   * Log level for SchemaCrawler. One of [OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST,
   * ALL]
   */
  @Parameter(property = "loglevel", defaultValue = "OFF")
  private String loglevel;
  /** SchemaCrawler command. */
  @Parameter(property = "command", required = true)
  private String command;
  /** Config file. */
  @Parameter(property = "config", defaultValue = "schemacrawler.config.properties", required = true)
  private File config;
  /**
   * Regular expression to match fully qualified column names, in the form
   * "CATALOGNAME.SCHEMANAME.TABLENAME.COLUMNNAME" - for example, .*\.STREET|.*\.PRICE matches
   * columns named STREET or PRICE in any table Columns that match the pattern are not displayed
   */
  @Parameter(property = "excludecolumns")
  private String excludecolumns;
  /**
   * Regular expression to match fully qualified parameter names. Parameters that match the pattern
   * are not displayed
   */
  @Parameter(property = "excludeparameters")
  private String excludeparameters;
  /**
   * The info level determines the amount of database metadata retrieved, and also determines the
   * time taken to crawl the schema.
   */
  @Parameter(property = "infolevel", defaultValue = "standard", required = true)
  private String infolevel;
  /**
   * The info level determines the amount of database metadata retrieved, and also determines the
   * time taken to crawl the schema.
   */
  @Parameter(property = "loadrowcounts", defaultValue = "false")
  private boolean loadrowcounts;
  /** Whether to hide tables with no data. */
  @Parameter(property = "noemptytables", defaultValue = "false")
  private boolean noemptytables;
  /** Whether to hide additional database information. */
  @Parameter(property = "noinfo", defaultValue = "true")
  private boolean noinfo;
  /** Whether to show table and column remarks. */
  @Parameter(property = "noremarks", defaultValue = "false")
  private boolean noremarks;
  /** Output format. */
  @Parameter(property = "outputformat", defaultValue = "html")
  private String outputformat;
  /** Output file. */
  @Parameter(property = "outputfile", defaultValue = "schemacrawler-output.html")
  private String outputfile;
  /** Database connection user password. */
  @Parameter(property = "password", defaultValue = "${schemacrawler.password}")
  private String password;
  /** The commandline dependencies. */
  @Parameter(property = "commandline.artifacts", required = true, readonly = true)
  private List pluginArtifacts;
  /** Whether to show portable database object names. */
  @Parameter(property = "portablenames", defaultValue = "false")
  private boolean portablenames;
  /**
   * Regular expression to match fully qualified routine names, in the form
   * "CATALOGNAME.SCHEMANAME.ROUTINENAME" - for example, .*\..*\.C.*|.*\..*\.P.* matches any
   * routines whose names start with C or P Routines that do not match the pattern are not displayed
   */
  @Parameter(property = "routines")
  private String routines;
  /** Schemas to include. */
  @Parameter(property = "schemas")
  private String schemas;
  /**
   * Regular expression to match fully qualified sequence names, in the form
   * "CATALOGNAME.SCHEMANAME.SEQUENCENAME" - for example, .*\..*\.C.*|.*\..*\.P.* Sequences that do
   * not match the pattern are not displayed.
   */
  @Parameter(property = "sequences")
  private String sequences;
  /** Sort columns in a table alphabetically. */
  @Parameter(property = "sortcolumns", defaultValue = "false")
  private boolean sortcolumns;
  /** Sort parameters in a routine alphabetically. */
  @Parameter(property = "sortparameters", defaultValue = "false")
  private boolean sortparameters;
  /** Sort tables alphabetically. */
  @Parameter(property = "sorttables", defaultValue = "true")
  private boolean sorttables;
  /**
   * Regular expression to match fully qualified synonym names, in the form
   * "CATALOGNAME.SCHEMANAME.SYNONYMNAME" - for example, .*\..*\.C.*|.*\..*\.P.* Synonyms that do
   * not match the pattern are not displayed.
   */
  @Parameter(property = "synonyms")
  private String synonyms;
  /**
   * Comma-separated list of table types of
   * TABLE,VIEW,SYSTEM_TABLE,GLOBAL_TEMPORARY,LOCAL_TEMPORARY,ALIAS
   */
  @Parameter(property = "table_types")
  private String tableTypes;

  /**
   * Regular expression to match fully qualified table names, in the form
   * "CATALOGNAME.SCHEMANAME.TABLENAME" - for example, .*\..*\.C.*|.*\..*\.P.* Tables that do not
   * match the pattern are not displayed.
   */
  @Parameter(property = "tables")
  private String tables;
  /** Title for the SchemaCrawler Report. */
  @Parameter(property = "title", defaultValue = "SchemaCrawler Report")
  private String title;
  /** Database connection string. */
  @Parameter(property = "url", defaultValue = "${schemacrawler.url}", required = true)
  private String url;
  /** Database connection user name. */
  @Parameter(property = "user", defaultValue = "${schemacrawler.user}", required = true)
  private String user;

  /**
   * {@inheritDoc}
   *
   * @see org.apache.maven.reporting.MavenReport#getDescription(java.util.Locale)
   */
  @Override
  public String getDescription(final Locale locale) {
    return getName(locale);
  }

  /**
   * {@inheritDoc}
   *
   * @see org.apache.maven.reporting.MavenReport#getName(java.util.Locale)
   */
  @Override
  public String getName(final Locale locale) {
    return "SchemaCrawler Report";
  }

  /**
   * {@inheritDoc}
   *
   * @see org.apache.maven.reporting.MavenReport#getOutputName()
   */
  @Override
  public String getOutputName() {
    return "schemacrawler-report";
  }

  @Override
  protected void executeReport(final Locale locale) throws MavenReportException {
    try {
      final Path outputFile = executeSchemaCrawler();
      final Path reportFile = Paths.get(getOutputDirectory(), getOutputFilename()).toAbsolutePath();

      Files.move(outputFile, reportFile, StandardCopyOption.REPLACE_EXISTING);
      final Log logger = getLog();
      logger.info("Generated SchemaCrawler report, " + reportFile);

      // Get the Maven Doxia Sink, which will be used to generate the
      // various elements of the document
      final Sink mainSink = getSink();
      if (mainSink == null) {
        throw new MavenReportException("Could not get the Doxia sink");
      }

      // Page title
      mainSink.head();
      mainSink.title();
      mainSink.text(getName(Locale.getDefault()));
      mainSink.title_();
      mainSink.head_();

      mainSink.body();

      // Heading 1
      mainSink.section1();
      mainSink.sectionTitle1();
      mainSink.text(getName(Locale.getDefault()));
      mainSink.sectionTitle1_();

      // Content
      mainSink.paragraph();
      mainSink.link(getOutputFilename());
      mainSink.text(title);
      mainSink.link_();
      mainSink.paragraph_();

      // Close
      mainSink.section1_();
      mainSink.body_();
    } catch (final Exception e) {
      throw new MavenReportException("Error executing SchemaCrawler report", e);
    }
  }

  private Path executeSchemaCrawler() throws Exception {

    final Map argsMap = new HashMap<>();

    if (config != null) {
      final Path configPath = config.toPath().toAbsolutePath();
      argsMap.put("--config-file", configPath.toString());
    }

    // Load command
    if (!isBlank(infolevel)) {
      argsMap.put("--info-level", infolevel);
    }
    if (loadrowcounts) {
      argsMap.put("--load-row-counts", Boolean.TRUE.toString());
    }

    // Limit command
    if (!isBlank(tableTypes)) {
      argsMap.put("--table-types", tableTypes);
    }
    if (schemas != null) {
      argsMap.put("--schemas", schemas);
    }
    if (synonyms != null) {
      argsMap.put("--synonyms", synonyms);
    }
    if (sequences != null) {
      argsMap.put("--sequences", sequences);
    }
    if (tables != null) {
      argsMap.put("--tables", tables);
    }
    if (routines != null) {
      argsMap.put("--routines", routines);
    }
    if (excludecolumns != null) {
      argsMap.put("--excludecolumns", excludecolumns);
    }
    if (excludeparameters != null) {
      argsMap.put("--excludeparameters", excludeparameters);
    }

    // Filter command
    if (noemptytables) {
      argsMap.put("--no-empty-tables", Boolean.TRUE.toString());
    }

    // Show command
    if (noinfo) {
      argsMap.put("--no-info", Boolean.TRUE.toString());
    }
    if (noremarks) {
      argsMap.put("--no-remarks", Boolean.TRUE.toString());
    }
    if (portablenames) {
      argsMap.put("--portable", PortableType.names.name());
    }

    // Sort command
    if (sorttables) {
      argsMap.put("--sort-tables", Boolean.TRUE.toString());
    }
    if (sortcolumns) {
      argsMap.put("--sort-columns", Boolean.TRUE.toString());
    }
    if (sortparameters) {
      argsMap.put("--sort-parameters", Boolean.TRUE.toString());
    }

    // Connect command
    argsMap.put("--url", url);
    argsMap.put("--user", user);
    if (password != null) {
      argsMap.put("--password", password);
    }

    // Log command
    argsMap.put("--log-level", loglevel);

    // Execute command
    if (!isBlank(title)) {
      argsMap.put("--title", title);
    }
    if (!isBlank(outputformat)) {
      argsMap.put("--output-format", outputformat);
    }
    if (!isBlank(outputformat)) {
      argsMap.put("--output-format", outputformat);
    }

    if (!isBlank(command)) {
      argsMap.put("--command", command);
    }

    // Output into a temporary file
    final Path outputFile =
        Paths.get(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString() + ".tmp")
            .toAbsolutePath()
            .normalize();
    argsMap.put("--output-file", outputFile.toString());

    // Build command-line
    final List argsList = new ArrayList<>();
    for (final Entry entry : argsMap.entrySet()) {
      argsList.add(entry.getKey());
      argsList.add(entry.getValue());
    }
    final String[] args = argsList.toArray(new String[0]);

    final Log logger = getLog();
    logger.info("Executing SchemaCrawler with: " + argsMap);

    // Run SchemaCrawler command-line
    Main.main(args);
    if (!Files.isReadable(outputFile)) {
      throw new IOException("SchemaCrawler report was not generated");
    }
    logger.info("Completed SchemaCrawler execution");

    return outputFile;
  }

  private String getOutputFilename() {
    if (outputfile == null || isBlank(outputfile)) {
      return String.format("schemacrawler-output.%s", outputformat);
    }
    return Paths.get(outputfile).getFileName().toString();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy