/*
*
* SchemaCrawler
* http://sourceforge.net/projects/schemacrawler
* Copyright (c) 2000-2010, 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.FileReader;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Locale;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.siterenderer.Renderer;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReport;
import org.apache.maven.reporting.MavenReportException;
import schemacrawler.schemacrawler.Config;
import schemacrawler.schemacrawler.ConnectionOptions;
import schemacrawler.schemacrawler.DatabaseConnectionOptions;
import schemacrawler.schemacrawler.InclusionRule;
import schemacrawler.schemacrawler.SchemaCrawlerOptions;
import schemacrawler.tools.commandline.InfoLevel;
import schemacrawler.tools.executable.Executable;
import schemacrawler.tools.executable.SchemaCrawlerExecutable;
import schemacrawler.tools.options.OutputFormat;
import schemacrawler.tools.options.OutputOptions;
import sf.util.ObjectToString;
import sf.util.Utility;
/**
* Generates a SchemaCrawler report of the database.
*
* @goal schemacrawler
* @execute phase="generate-sources"
* @phase site
*/
public class SchemaCrawlerMojo
extends AbstractMavenReport
implements MavenReport
{
/**
* @parameter default-value="${project}"
* @required
* @readonly
*/
private MavenProject project;
/**
* JDBC driver classpath.
*
* @parameter expression="${jdbc.driver.classpath}"
* alias="jdbc.driver.classpath"
* @required
*/
private String jdbcDriverClasspath;
/**
* Config file.
*
* @parameter expression="${config}" alias="config"
* default-value="config.properties"
* @required
*/
private String config;
/**
* Config override file.
*
* @parameter expression="${config-override}" alias="config-override"
* default-value="schemacrawler.config.override.properties"
*/
private String configOverride;
/**
* JDBC driver class name.
*
* @parameter expression="${driver}" alias="driver"
* @required
*/
private String driver;
/**
* Database connection string.
*
* @parameter expression="${url}" alias="url"
* @required
*/
private String url;
/**
*Database connection user name.
*
* @parameter expression="${user}" alias="user"
* @required
*/
private String user;
/**
*Database connection user password.
*
* @parameter expression="${password}" alias="password"
* @required
*/
private String password;
/**
* Command.
*
* @parameter expression="${command}" alias="command"
* @required
*/
private String command;
/**
* Sort tables alphabetically.
*
* @parameter expression="${sorttables}" alias="sorttables"
*/
private final String sorttables = "true";
/**
* Sort columns in a table alphabetically.
*
* @parameter expression="${sortcolumns}" alias="sortcolumns"
*/
private final String sortcolumns = "false";
/**
* Sort parameters in a stored procedure alphabetically.
*
* @parameter expression="${sortinout}" alias="sortinout"
*/
private final String sortinout = "false";
/**
* The info level determines the amount of database metadata
* retrieved, and also determines the time taken to crawl the schema.
*
* @parameter expression="${infolevel}" alias="infolevel"
*/
private final String infolevel = InfoLevel.standard.name();
/**
* @parameter expression="${schemas}" alias="schemas"
*/
private final String schemas = InclusionRule.ALL;
/**
* Comma-separated list of table types of
* TABLE,VIEW,SYSTEM_TABLE,GLOBAL_TEMPORARY,LOCAL_TEMPORARY,ALIAS
*
* @parameter expression="${table_types}" alias="table_types"
*/
private String table_types;
/**
* Whether to show procedures, or not.
*
* @parameter expression="${show_stored_procedures}"
* alias="show_stored_procedures"
*/
private final String show_stored_procedures = Boolean.TRUE.toString();
/**
* 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 expression="${tables}" alias="tables"
*/
private final String tables = InclusionRule.ALL;
/**
* 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 expression="${excludecolumns}" alias="excludecolumns"
*/
private final String excludecolumns = InclusionRule.NONE;
/**
* Regular expression to match fully qualified procedure names, in the
* form "CATALOGNAME.SCHEMANAME.PROCEDURENAME" - for example,
* .*\.C.*|.*\.P.* matches any procedures whose names start with C or
* P Procedures that do not match the pattern are not displayed
*
* @parameter expression="${schemas}" alias="schemas"
*/
private final String procedures = InclusionRule.ALL;
/**
* Regular expression to match fully qualified parameter names.
* Parameters that match the pattern are not displayed
*
* @parameter expression="${schemas}" alias="schemas"
*/
private final String excludeinout = InclusionRule.NONE;
/**
* {@inheritDoc}
*
* @see org.apache.maven.reporting.MavenReport#getDescription(java.util.Locale)
*/
public String getDescription(final Locale locale)
{
return "SchemaCrawler Report";
}
/**
* {@inheritDoc}
*
* @see org.apache.maven.reporting.MavenReport#getName(java.util.Locale)
*/
public String getName(final Locale locale)
{
return "SchemaCrawler Report";
}
/**
* {@inheritDoc}
*
* @see org.apache.maven.reporting.MavenReport#getOutputName()
*/
public String getOutputName()
{
return "schemacrawler";
}
private OutputOptions createOutputOptions(final File outputFile)
{
final OutputOptions outputOptions = new OutputOptions();
outputOptions.setOutputFormatValue(OutputFormat.html.name());
outputOptions.setAppendOutput(false);
outputOptions.setNoHeader(true);
outputOptions.setNoFooter(true);
outputOptions.setOutputFileName(outputFile.getAbsolutePath());
return outputOptions;
}
private SchemaCrawlerOptions createSchemaCrawlerOptions()
{
final SchemaCrawlerOptions schemaCrawlerOptions = new SchemaCrawlerOptions();
if (!Utility.isBlank(table_types))
{
schemaCrawlerOptions.setTableTypes(table_types);
}
schemaCrawlerOptions.setShowStoredProcedures(Boolean
.parseBoolean(show_stored_procedures));
schemaCrawlerOptions.setAlphabeticalSortForTables(Boolean
.parseBoolean(sorttables));
schemaCrawlerOptions.setAlphabeticalSortForTableColumns(Boolean
.parseBoolean(sortcolumns));
schemaCrawlerOptions.setAlphabeticalSortForProcedureColumns(Boolean
.parseBoolean(sortinout));
schemaCrawlerOptions.setSchemaInfoLevel(InfoLevel.valueOf(infolevel)
.getSchemaInfoLevel());
schemaCrawlerOptions
.setSchemaInclusionRule(new InclusionRule(schemas, InclusionRule.NONE));
schemaCrawlerOptions
.setTableInclusionRule(new InclusionRule(tables, InclusionRule.NONE));
schemaCrawlerOptions
.setProcedureInclusionRule(new InclusionRule(procedures,
InclusionRule.NONE));
schemaCrawlerOptions
.setColumnInclusionRule(new InclusionRule(InclusionRule.ALL,
excludecolumns));
schemaCrawlerOptions
.setProcedureColumnInclusionRule(new InclusionRule(InclusionRule.ALL,
excludeinout));
return schemaCrawlerOptions;
}
/**
* The JDBC driver classpath comes from the configuration of the
* SchemaCrawler plugin. The current classloader needs to be "fixed"
* to include the JDBC driver in the classpath.
*
* @throws MavenReportException
*/
private void fixClassPath()
throws MavenReportException
{
URL[] jdbcJarUrls = new URL[0];
try
{
final String[] jdbcJarPaths = jdbcDriverClasspath.split(System
.getProperty("path.separator"));
jdbcJarUrls = new URL[jdbcJarPaths.length];
for (int i = 0; i < jdbcJarPaths.length; i++)
{
final String jdbcJarPath = jdbcJarPaths[i];
jdbcJarUrls[i] = new File(jdbcJarPath).getCanonicalFile().toURI()
.toURL();
}
final Method addUrlMethod = URLClassLoader.class
.getDeclaredMethod("addURL", new Class[] {
URL.class
});
final URLClassLoader classLoader = (URLClassLoader) getClass()
.getClassLoader();
addUrlMethod.setAccessible(true);
for (final URL jdbcJarUrl: jdbcJarUrls)
{
addUrlMethod.invoke(classLoader, jdbcJarUrl);
}
getLog().info("Fixed SchemaCrawler classpath: "
+ Arrays.asList(classLoader.getURLs()));
}
catch (final Exception e)
{
throw new MavenReportException("Error fixing classpath with "
+ Arrays.asList(jdbcJarUrls), e);
}
}
@Override
protected void executeReport(final Locale locale)
throws MavenReportException
{
final Executable executable = new SchemaCrawlerExecutable(command);
try
{
fixClassPath();
final File outputFile = File.createTempFile("schemacrawler.report.",
".html");
final Config additionalConfiguration = Config
.load(config, configOverride);
// Execute SchemaCrawler
executable.setOutputOptions(createOutputOptions(outputFile));
executable.setSchemaCrawlerOptions(createSchemaCrawlerOptions());
executable.setAdditionalConfiguration(additionalConfiguration);
final ConnectionOptions connectionOptions = new DatabaseConnectionOptions(driver,
url);
connectionOptions.setUser(user);
connectionOptions.setPassword(password);
getLog().debug(ObjectToString.toString(executable));
executable.execute(connectionOptions.createConnection());
// Create report
final String styleSheet = Utility
.readResourceFully("/schemacrawler-report-output.css");
final Sink sink = getSink();
getLog().info(sink.getClass().getName());
sink.head();
sink.title();
sink.text("SchemaCrawler Report");
sink.title_();
sink.rawText("<style type='text/css'>" + Utility.NEWLINE + styleSheet
+ Utility.NEWLINE + " </style>" + Utility.NEWLINE);
sink.head_();
sink.body();
sink.rawText(Utility.readFully(new FileReader(outputFile)));
sink.body_();
sink.flush();
sink.close();
}
catch (final Exception e)
{
throw new MavenReportException("Error executing:\n"
+ ObjectToString.toString(executable), e);
}
}
/**
* @see org.apache.maven.reporting.AbstractMavenReport#getOutputDirectory()
*/
@Override
protected String getOutputDirectory()
{
return null; // Unused in the Maven API
}
/**
* @see org.apache.maven.reporting.AbstractMavenReport#getProject()
*/
@Override
protected MavenProject getProject()
{
return project;
}
/**
* @see org.apache.maven.reporting.AbstractMavenReport#getSiteRenderer()
*/
@Override
protected Renderer getSiteRenderer()
{
return null; // Unused in the Maven API
}
}