com.freetmp.maven.mbg.extend.plugin.MyBatisGeneratorMojo Maven / Gradle / Ivy
The newest version!
package com.freetmp.maven.mbg.extend.plugin;
import com.freetmp.mbg.comment.CommentGenerator;
import com.freetmp.mbg.constant.DatabaseType;
import com.freetmp.mbg.plugin.*;
import com.freetmp.mbg.plugin.batch.BatchInsertPlugin;
import com.freetmp.mbg.plugin.batch.BatchUpdatePlugin;
import com.freetmp.mbg.plugin.geom.PostgisGeoPlugin;
import com.freetmp.mbg.plugin.page.*;
import com.freetmp.mbg.plugin.upsert.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.api.ShellCallback;
import org.mybatis.generator.config.*;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.ObjectFactory;
import org.mybatis.generator.internal.util.ClassloaderUtility;
import org.mybatis.generator.internal.util.StringUtility;
import org.mybatis.generator.internal.util.messages.Messages;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;
/**
* Created by LiuPin on 2015/1/30.
*/
@Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class MyBatisGeneratorMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", required = true, readonly = true)
private MavenProject project;
@Parameter(property = "mybatis.generator.outputDirectory",
defaultValue = "${project.build.directory}/generated-sources/mybatis-generator", required = true)
private File outputDirectory;
/**
* Location of the configuration file.
*/
@Parameter(property = "mybatis.generator.configurationFile",
defaultValue = "${basedir}/src/main/resources/generatorConfig.xml", required = true)
private File configurationFile;
/**
* Specifies whether the mojo writes progress messages to the log
*/
@Parameter(property = "mybatis.generator.verbose", defaultValue = "false")
private boolean verbose;
/**
* Specifies whether the mojo overwrites existing files. Default is false.
*/
@Parameter(property = "mybatis.generator.overwrite", defaultValue = "false")
private boolean overwrite;
/**
* Location of a SQL script file to run before generating code. If null,
* then no script will be run. If not null, then jdbcDriver, jdbcURL must be
* supplied also, and jdbcUserId and jdbcPassword may be supplied.
*/
@Parameter(property = "mybatis.generator.sqlScript")
private String sqlScript;
/**
* JDBC Driver to use if a sql.script.file is specified
*/
@Parameter(property = "mybatis.generator.jdbcDriver")
private String jdbcDriver;
/**
* JDBC URL to use if a sql.script.file is specified
*/
@Parameter(property = "mybatis.generator.jdbcURL")
private String jdbcURL;
/**
* JDBC user ID to use if a sql.script.file is specified
*/
@Parameter(property = "mybatis.generator.jdbcUserId")
private String jdbcUserId;
/**
* JDBC password to use if a sql.script.file is specified
*/
@Parameter(property = "mybatis.generator.jdbcPassword")
private String jdbcPassword;
/**
* Comma delimited list of table names to generate
*/
@Parameter(property = "mybatis.generator.tableNames")
private String tableNames;
/**
* Comma delimited list of contexts to generate
*/
@Parameter(property = "mybatis.generator.contexts")
private String contexts;
/**
* set true to add the generated sources and xml mappers to the compile phase
*/
@Parameter(defaultValue = "false", property = "x.mybatis.generator.addToProjectAsCompileSource")
private boolean addToProjectAsCompileSource;
/**
* set true to add the generated sources and xml mappers to the test compile phase
*/
@Parameter(defaultValue = "true", property = "x.mybatis.generator.addToProjectAsTestCompileSource")
private boolean addToProjectAsTestCompileSource;
/**
* set true to disable the extend methods(include batch,upsert etc)
*/
@Parameter(defaultValue = "false", property = "x.mybatis.generator.disableExtendMethods")
private boolean disableExtendMethods;
/**
* set true to disable the geom support
*/
@Parameter(defaultValue = "false", property = "x.mybatis.generator.disableGeom")
private boolean disableGeom;
/**
* set true to disable the name conversion
*/
@Parameter(defaultValue = "false", property = "x.mybatis.generator.disableNameConversion")
private boolean disableNameConversion;
/**
* set true to disable the pagination
*/
@Parameter(defaultValue = "false", property = "x.mybatis.generator.disablePagination")
private boolean disablePagination;
/**
* set true to disable the content merge
*/
@Parameter(defaultValue = "false", property = "x.mybatis.generator.disableMergeSupport")
private boolean disableMergeSupport;
/**
* set true to enable QueryDsl support
*/
@Parameter(defaultValue = "false", property = "x.mybatis.generator.enableQueryDslSupport")
private boolean enableQueryDslSupport;
/**
* the regex pattern used to match the word in the column name
*/
@Parameter(defaultValue = "[a-zA-Z0-9]+", property = "x.mybatis.generator.columnPattern")
private String columnPattern;
/**
* the srid used by the geom to standard space identifier quote
*/
@Parameter(defaultValue = "3857", property = "x.mybatis.generator.srid")
private String srid;
/**
* the path to the i18n resources directory
*/
@Parameter(property = "x.mybatis.generator.i18nPath")
private File i18nPath;
/**
* the locale used by the i18n path
*/
@Parameter(defaultValue = "en_US", property = "x.mybatis.generator.locale")
private String locale;
/**
* the start year of the project used by copyright generated
*/
@Parameter(property = "x.mybatis.generator.projectStartYear")
private String projectStartYear;
public void execute() throws MojoExecutionException {
printAnnounce();
// add resource directories to the classpath. This is required to support
// use of a properties file in the build. Typically, the properties file
// is in the project's source tree, but the plugin classpath does not
// include the project classpath.
@SuppressWarnings("unchecked")
List resources = project.getResources();
List resourceDirectories = new ArrayList();
for (Resource resource : resources) {
resourceDirectories.add(resource.getDirectory());
}
ClassLoader cl = ClassloaderUtility.getCustomClassloader(resourceDirectories);
ObjectFactory.addResourceClassLoader(cl);
if (configurationFile == null) {
throw new MojoExecutionException(
Messages.getString("RuntimeError.0")); //$NON-NLS-1$
}
List warnings = new ArrayList();
if (!configurationFile.exists()) {
throw new MojoExecutionException(Messages.getString(
"RuntimeError.1", configurationFile.toString())); //$NON-NLS-1$
}
runScriptIfNecessary();
Set fullyQualifiedTables = new HashSet();
if (StringUtility.stringHasValue(tableNames)) {
StringTokenizer st = new StringTokenizer(tableNames, ","); //$NON-NLS-1$
while (st.hasMoreTokens()) {
String s = st.nextToken().trim();
if (s.length() > 0) {
fullyQualifiedTables.add(s);
}
}
}
Set contextsToRun = new HashSet();
if (StringUtility.stringHasValue(contexts)) {
StringTokenizer st = new StringTokenizer(contexts, ","); //$NON-NLS-1$
while (st.hasMoreTokens()) {
String s = st.nextToken().trim();
if (s.length() > 0) {
contextsToRun.add(s);
}
}
}
try {
ConfigurationParser cp = new ConfigurationParser(
project.getProperties(), warnings);
Configuration config = cp.parseConfiguration(configurationFile);
ShellCallback callback = new MavenShellCallback(this, overwrite);
// 扩展原配置
extendConfig(config, (MavenShellCallback) callback);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
callback, warnings);
myBatisGenerator.generate(new MavenProgressCallback(getLog(),
verbose), contextsToRun, fullyQualifiedTables);
} catch (XMLParserException e) {
for (String error : e.getErrors()) {
getLog().error(error);
}
throw new MojoExecutionException(e.getMessage());
} catch (SQLException e) {
throw new MojoExecutionException(e.getMessage());
} catch (IOException e) {
throw new MojoExecutionException(e.getMessage());
} catch (InvalidConfigurationException e) {
for (String error : e.getErrors()) {
getLog().error(error);
}
throw new MojoExecutionException(e.getMessage());
} catch (InterruptedException e) {
// ignore (will never happen with the DefaultShellCallback)
;
}
for (String error : warnings) {
getLog().warn(error);
}
if (addToProjectAsCompileSource && project != null && outputDirectory != null && outputDirectory.exists()) {
project.addCompileSourceRoot(outputDirectory.getAbsolutePath());
Resource resource = new Resource();
resource.setDirectory(outputDirectory.getAbsolutePath());
resource.addInclude("**/*.xml");
project.addResource(resource);
}
if (addToProjectAsTestCompileSource && project != null && outputDirectory != null && outputDirectory.exists()) {
project.addTestCompileSourceRoot(outputDirectory.getAbsolutePath());
Resource resource = new Resource();
resource.setDirectory(outputDirectory.getAbsolutePath());
resource.addInclude("**/*.xml");
project.addTestResource(resource);
}
}
/**
* 打印一些通知
*/
private void printAnnounce() {
getLog().info("Welcome using the XMBG!");
getLog().info("issue report: https://github.com/beihaifeiwu/dolphin/issues");
}
/**
* 扩展配置实现XMBG
*
* @param config
* @param callback
*/
private void extendConfig(Configuration config, MavenShellCallback callback) {
List contexts = config.getContexts();
if (contexts == null) return;
// fix java file encoding
for (Context context : contexts) {
context.addProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING, "UTF-8");
}
if (!disableNameConversion) {
PluginConfiguration pluginConfiguration = new PluginConfiguration();
pluginConfiguration.setConfigurationType(ColumnNameConversionPlugin.class.getTypeName());
pluginConfiguration.addProperty(ColumnNameConversionPlugin.COLUMN_PATTERN_NAME, columnPattern);
addToContext(contexts, pluginConfiguration);
if (verbose) getLog().info("enable name conversion service");
}
if (!disableExtendMethods) {
PluginConfiguration pluginConfiguration = new PluginConfiguration();
pluginConfiguration.setConfigurationType(BatchInsertPlugin.class.getTypeName());
addToContext(contexts, pluginConfiguration);
if (verbose) getLog().info("enable batch insert service");
pluginConfiguration = new PluginConfiguration();
pluginConfiguration.setConfigurationType(BatchUpdatePlugin.class.getTypeName());
addToContext(contexts, pluginConfiguration);
if (verbose) getLog().info("enable batch update service");
for(Context context : contexts){
chooseUpsertPlugin(context);
}
}
if (!disableGeom) {
for (Context context : contexts) {
chooseGeomPlugin(context);
}
}
if (!disablePagination) {
for (Context context : contexts) {
choosePaginationPlugin(context);
}
}
if (overwrite) {
PluginConfiguration pluginConfiguration = new PluginConfiguration();
pluginConfiguration.setConfigurationType(MapperOverwriteEnablePlugin.class.getTypeName());
addToContext(contexts, pluginConfiguration);
if (verbose) getLog().info("enable mapper overwrite service");
}
if (enableQueryDslSupport) {
PluginConfiguration pluginConfiguration = new PluginConfiguration();
pluginConfiguration.setConfigurationType(QueryDslPlugin.class.getTypeName());
addToContext(contexts, pluginConfiguration);
if (verbose) getLog().info("enable querydsl support service");
}
if (!disableMergeSupport) {
callback.setMergeSupported(true);
PluginConfiguration pluginConfiguration = new PluginConfiguration();
pluginConfiguration.setConfigurationType(XMLMergePlugin.class.getTypeName());
pluginConfiguration.addProperty(XMLMergePlugin.ROOTDIR_NAME, outputDirectory.getAbsolutePath());
addToContext(contexts, pluginConfiguration);
if (verbose) getLog().info("enable content merge service");
}
// leave the cg for the last
extendCG(config, contexts);
}
/**
* extend origin mbg the ability for generating comments
*/
private void extendCG(Configuration config, List contexts) {
// just use the extended comment generator
PluginConfiguration pluginConfiguration = new PluginConfiguration();
pluginConfiguration.setConfigurationType(CommentsWavePlugin.class.getTypeName());
addToContext(contexts, pluginConfiguration);
if (verbose) getLog().info("enable comment wave service");
for (Context context : config.getContexts()) {
context.getCommentGeneratorConfiguration().setConfigurationType(CommentGenerator.class.getTypeName());
if (i18nPath != null && i18nPath.exists()) {
context.getCommentGeneratorConfiguration().addProperty(CommentGenerator.XMBG_CG_I18N_PATH_KEY, i18nPath.getAbsolutePath());
}
if (StringUtils.isEmpty(projectStartYear)) {
projectStartYear = CommentGenerator.XMBG_CG_PROJECT_START_DEFAULT_YEAR;
}
context.getCommentGeneratorConfiguration().addProperty(CommentGenerator.XMBG_CG_PROJECT_START_YEAR, projectStartYear);
context.getCommentGeneratorConfiguration().addProperty(CommentGenerator.XMBG_CG_I18N_LOCALE_KEY, locale);
}
if (verbose) getLog().info("replace the origin comment generator");
}
/**
* 根据context中的driver配置检测数据库的类别,并为其添加相应的分页插件
*
* @param context
*/
void choosePaginationPlugin(Context context) {
DatabaseType type = detectDB(context);
PluginConfiguration pluginConfiguration = new PluginConfiguration();
switch (type) {
case MYSQL:
pluginConfiguration.setConfigurationType(MySqlPaginationPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if (verbose) getLog().info("enable pagination service with mysql for context " + context.getId());
break;
case POSTGRESQL:
pluginConfiguration.setConfigurationType(PostgreSQLPaginationPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if (verbose) getLog().info("enable pagination service with postgresql for context " + context.getId());
break;
case SQLSERVER:
pluginConfiguration.setConfigurationType(SQLServerPaginationPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if (verbose) getLog().info("enable pagination service with sqlserver for context " + context.getId());
break;
case DB2:
pluginConfiguration.setConfigurationType(DB2PaginationPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if (verbose) getLog().info("enable pagination service with db2 for context " + context.getId());
break;
case ORACLE:
pluginConfiguration.setConfigurationType(OraclePaginationPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if (verbose) getLog().info("enable pagination service with oracle for context " + context.getId());
break;
case HSQLDB:
pluginConfiguration.setConfigurationType(HsqldbPaginationPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if (verbose) getLog().info("enable pagination service with hsqldb for context " + context.getId());
break;
}
}
/**
* 根据context中的driver配置检测数据库的类别,并为其添加相应的Upsert插件
* @param context
*/
void chooseUpsertPlugin(Context context) {
DatabaseType type = detectDB(context);
PluginConfiguration pluginConfiguration = new PluginConfiguration();
switch (type){
case MYSQL:
pluginConfiguration.setConfigurationType(MySqlUpsertPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if(verbose)getLog().info("enable upsert service with mysql for context " + context.getId());
break;
case POSTGRESQL:
pluginConfiguration.setConfigurationType(PostgreSQLUpsertPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if(verbose)getLog().info("enable upsert service with postgresql for context " + context.getId());
break;
case SQLSERVER:
pluginConfiguration.setConfigurationType(SQLServerUpsertPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if(verbose)getLog().info("enable upsert service with sqlserver for context " + context.getId());
break;
case DB2:
pluginConfiguration.setConfigurationType(DB2UpsertPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if(verbose)getLog().info("enable upsert service with db2 for context " + context.getId());
break;
case ORACLE:
pluginConfiguration.setConfigurationType(OracleUpsertPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if(verbose)getLog().info("enable upsert service with oracle for context " + context.getId());
break;
case HSQLDB:
pluginConfiguration.setConfigurationType(HsqldbUpsertPlugin.class.getTypeName());
context.addPluginConfiguration(pluginConfiguration);
if(verbose)getLog().info("enable upsert service with hsqldb for context " + context.getId());
break;
}
}
void chooseGeomPlugin(Context context) {
DatabaseType type = detectDB(context);
PluginConfiguration pluginConfiguration = new PluginConfiguration();
switch (type) {
case MYSQL:
break;
case POSTGRESQL:
pluginConfiguration.setConfigurationType(PostgisGeoPlugin.class.getTypeName());
pluginConfiguration.addProperty(PostgisGeoPlugin.SRID_NAME, srid);
context.addPluginConfiguration(pluginConfiguration);
if (verbose) getLog().info("enable geom service with postgresql for context " + context.getId());
break;
}
}
private DatabaseType detectDB(Context context) {
JDBCConnectionConfiguration jdbcConnectionConfiguration = context.getJdbcConnectionConfiguration();
String url = jdbcConnectionConfiguration.getConnectionURL();
int start = url.indexOf(":");
if (start == -1) return DatabaseType.UNKNOWN;
start += 1;
int end = url.indexOf(":", start);
if (end == -1) return DatabaseType.UNKNOWN;
String dbName = url.substring(start, end).toUpperCase();
try {
return DatabaseType.valueOf(dbName);
} catch (IllegalArgumentException e) {
getLog().warn("cannot detect db type from the context",e);
}
return DatabaseType.UNKNOWN;
}
private void addToContext(List contexts, PluginConfiguration pluginConfiguration) {
for (Context context : contexts) {
context.addPluginConfiguration(pluginConfiguration);
}
}
private void runScriptIfNecessary() throws MojoExecutionException {
if (sqlScript == null) {
return;
}
SqlScriptRunner scriptRunner = new SqlScriptRunner(sqlScript,
jdbcDriver, jdbcURL, jdbcUserId, jdbcPassword);
scriptRunner.setLog(getLog());
scriptRunner.executeScript();
}
public File getOutputDirectory() {
return outputDirectory;
}
}