Skip to content

Commit

Permalink
generate entities command works correctly (but still needs polishing)
Browse files Browse the repository at this point in the history
  • Loading branch information
koentsje committed Sep 12, 2013
1 parent 74d78de commit 986baf6
Show file tree
Hide file tree
Showing 6 changed files with 343 additions and 8 deletions.
9 changes: 9 additions & 0 deletions impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,19 @@
<artifactId>projects-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.forge.addon</groupId>
<artifactId>parser-java-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.forge.addon</groupId>
<artifactId>javaee-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-tools</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
package org.hibernate.forge.addon.generate;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

import javax.inject.Inject;

import org.hibernate.cfg.JDBCMetaDataConfiguration;
import org.hibernate.cfg.reveng.DefaultReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.ReverseEngineeringSettings;
import org.hibernate.cfg.reveng.ReverseEngineeringStrategy;
import org.hibernate.forge.addon.util.ConnectionProfile;
import org.hibernate.forge.addon.util.DelegatingDriver;
import org.hibernate.forge.addon.util.UrlClassLoaderExecutor;
import org.hibernate.tool.hbm2x.ArtifactCollector;
import org.hibernate.tool.hbm2x.POJOExporter;
import org.jboss.forge.addon.javaee.facets.PersistenceFacet;
import org.jboss.forge.addon.parser.java.facets.JavaSourceFacet;
import org.jboss.forge.addon.projects.Project;
import org.jboss.forge.addon.projects.facets.MetadataFacet;
import org.jboss.forge.addon.projects.ui.AbstractProjectCommand;
Expand All @@ -24,13 +44,62 @@ public class GenerateEntitiesCommand extends AbstractProjectCommand
private static String COMMAND_DESCRIPTION = "Command to generate Java EE entities from database tables.";

@Inject
@WithAttributes(label = "Target package", type = InputType.JAVA_PACKAGE_PICKER)
@WithAttributes(
label = "Target package",
type = InputType.JAVA_PACKAGE_PICKER,
description = "The name of the target package in which to generate the entities",
required = true)
private UIInput<String> targetPackage;

@Inject
@WithAttributes(
label = "JDBC URL",
description = "The jdbc url for the database tables",
required = true)
private UIInput<String> jdbcUrl;

@Inject
@WithAttributes(
label = "User Name",
description = "The user name for the database connection",
required = true)
private UIInput<String> userName;

@Inject
@WithAttributes(
label = "User Password",
description = "The password for the database connection",
required = false,
defaultValue = "")
private UIInput<String> userPassword;

@Inject
@WithAttributes(
label = "Hibernate Dialect",
description = "The Hibernate dialect to use",
required = true)
private UIInput<String> hibernateDialect;

@Inject
@WithAttributes(
label = "Driver Location",
description = "The location of the jar file that contains the JDBC driver",
required = true)
private UIInput<String> driverLocation;

@Inject
@WithAttributes(
label = "Driver Class",
description = "The class name of the JDBC driver",
required = true)
private UIInput<String> driverClass;

@Override
public Metadata getMetadata()
{
return Metadata.from(super.getMetadata(), getClass()).name(COMMAND_NAME)
return Metadata
.from(super.getMetadata(), getClass())
.name(COMMAND_NAME)
.description(COMMAND_DESCRIPTION)
.category(Categories.create(COMMAND_CATEGORY));
}
Expand All @@ -42,13 +111,33 @@ public void initializeUI(UIBuilder builder) throws Exception
MetadataFacet facet = project.getFacet(MetadataFacet.class);
String topLevelPackage = facet.getTopLevelPackage();
targetPackage.setDefaultValue(topLevelPackage);
builder.add(targetPackage);
builder
.add(targetPackage)
.add(jdbcUrl)
.add(userName)
.add(userPassword)
.add(hibernateDialect)
.add(driverLocation)
.add(driverClass);
}

@Override
public Result execute(UIContext context)
{
return Results.success("Parameters " + getParameters() + " are captured.");
ConnectionProfile cp = buildConnectionProfile();
JDBCMetaDataConfiguration jmdc = configureMetaData(cp);
jmdc.setReverseEngineeringStrategy(createReverseEngineeringStrategy());
try
{
doReverseEngineering(cp.driver, cp.path, jmdc);
}
catch (Throwable t)
{
t.printStackTrace();
return Results.fail("An unexpected error happened during reverse engineering.");
}
exportNewEntities(jmdc, getSelectedProject(context));
return Results.success("Entities are generated succesfully.");
}

protected String getParameters()
Expand All @@ -61,16 +150,144 @@ protected boolean isProjectRequired()
{
return true;
}

@Override
public boolean isEnabled(UIContext context)
{
Project project = getSelectedProject(context);
if (project != null) {
if (project != null)
{
return project.hasFacet(PersistenceFacet.class) && super.isEnabled(context);
} else {
}
else
{
return false;
}
}


private ConnectionProfile buildConnectionProfile()
{
ConnectionProfile result = new ConnectionProfile();
result.url = jdbcUrl.getValue();
result.user = userName.getValue();
result.password = userPassword.getValue();
result.dialect = hibernateDialect.getValue();
result.driver = driverClass.getValue();
result.path = driverLocation.getValue();
return result;
}

private JDBCMetaDataConfiguration configureMetaData(
ConnectionProfile cp)
{
JDBCMetaDataConfiguration jmdc = new JDBCMetaDataConfiguration();
Properties properties = new Properties();
properties.setProperty("hibernate.connection.driver_class", cp.driver);
properties.setProperty("hibernate.connection.username", cp.user);
properties.setProperty("hibernate.dialect", cp.dialect);
properties.setProperty("hibernate.connection.password",
cp.password == null ? "" : cp.password);
properties.setProperty("hibernate.connection.url", cp.url);
jmdc.setProperties(properties);
return jmdc;
}

private ReverseEngineeringStrategy createReverseEngineeringStrategy()
{
ReverseEngineeringStrategy strategy = new DefaultReverseEngineeringStrategy();
ReverseEngineeringSettings revengsettings =
new ReverseEngineeringSettings(strategy)
.setDefaultPackageName(targetPackage.getValue())
.setDetectManyToMany(true)
.setDetectOneToOne(true)
.setDetectOptimisticLock(true);
strategy.setSettings(revengsettings);
return strategy;
}

private void doReverseEngineering(
final String driver,
final String path,
final JDBCMetaDataConfiguration jmdc) throws Throwable
{
try
{
UrlClassLoaderExecutor.execute(getDriverUrls(path), new Runnable()
{
@Override
public void run()
{
try
{
Driver jdbcDriver = (Driver) Class.forName(
driver,
true,
Thread.currentThread().getContextClassLoader()).newInstance();
DriverManager.registerDriver(new DelegatingDriver(jdbcDriver));
jmdc.readFromJDBC();
jmdc.buildMappings();
}
catch (Exception e)
{
e.printStackTrace();
throw new RuntimeException("Exception in runnable", e);
}
}
});
}
catch (RuntimeException e)
{
e.printStackTrace();
if ("Exception in runnable".equals(e.getMessage()) && e.getCause() != null)
{
throw e.getCause();
}
}
}

private URL[] getDriverUrls(String path) throws MalformedURLException
{
ArrayList<URL> urls = new ArrayList<URL>();
urls.add(new File(path).toURI().toURL());
return urls.toArray(new URL[urls.size()]);
}

private void exportNewEntities(JDBCMetaDataConfiguration jmdc, Project project)
{
Iterator<?> iter = jmdc.getTableMappings();
int count = 0;
while (iter.hasNext())
{
count++;
iter.next();
}
System.out.println("Found " + count + " tables in datasource");
JavaSourceFacet java = project.getFacet(JavaSourceFacet.class);
POJOExporter pj = new POJOExporter(jmdc, java.getSourceFolder()
.getUnderlyingResourceObject());
Properties pojoProperties = new Properties();
pojoProperties.setProperty("jdk5", "true");
pojoProperties.setProperty("ejb3", "true");
pj.setProperties(pojoProperties);

ArtifactCollector artifacts = new ArtifactCollector()
{
@Override
public void addFile(final File file, final String type)
{
System.out.println("Generated " + type + " at " + file.getPath());
super.addFile(file, type);
}
};
pj.setArtifactCollector(artifacts);
pj.start();
Set<?> fileTypes = artifacts.getFileTypes();
for (Iterator<?> iterator = fileTypes.iterator(); iterator.hasNext();)
{
String type = (String) iterator.next();
System.out.println("Generated " + artifacts.getFileCount(type) + " "
+ type + " files.");
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.hibernate.forge.addon.util;

public class ConnectionProfile {

public String name;
public String dialect;
public String driver;
public String path;
public String url;
public String user;
public String password;
public boolean savePassword;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.hibernate.forge.addon.util;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.util.Properties;
import java.util.logging.Logger;

public class DelegatingDriver implements Driver
{
private final Driver driver;

public DelegatingDriver(Driver driver)
{
if (driver == null)
{
throw new IllegalArgumentException("Driver must not be null.");
}
this.driver = driver;
}

public Connection connect(String url, Properties info) throws SQLException
{
return driver.connect(url, info);
}

public boolean acceptsURL(String url) throws SQLException
{
return driver.acceptsURL(url);
}

public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException
{
return driver.getPropertyInfo(url, info);
}

public int getMajorVersion()
{
return driver.getMajorVersion();
}

public int getMinorVersion()
{
return driver.getMinorVersion();
}

public boolean jdbcCompliant()
{
return driver.jdbcCompliant();
}

public Logger getParentLogger()
{
// TODO Auto-generated method stub
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.hibernate.forge.addon.util;

import java.net.URL;
import java.net.URLClassLoader;

public class UrlClassLoaderExecutor {

public static void execute(URL[] urls, Runnable runnable) {
ClassLoader savedClassLoader = Thread.currentThread().getContextClassLoader();
try {
URLClassLoader newClassLoader = new URLClassLoader(urls, savedClassLoader);
Thread.currentThread().setContextClassLoader(newClassLoader);
runnable.run();
} finally {
Thread.currentThread().setContextClassLoader(savedClassLoader);
}
}

}

0 comments on commit 986baf6

Please sign in to comment.