Add a Dialect report
Also added * H2Dialect#getMinimumSupportedVersion * DerbyDialect#getMinimumSupportedVersion
This commit is contained in:
parent
3ae07666ab
commit
c6389efb1b
|
@ -267,6 +267,33 @@ tasks.register('renderLoggingReport', AsciidoctorTask) { task ->
|
|||
}
|
||||
}
|
||||
|
||||
tasks.register('renderDialectReport', AsciidoctorTask) { task ->
|
||||
group 'Documentation'
|
||||
description = 'Renders the ORM Dialect report in HTML format using Asciidoctor.'
|
||||
dependsOn tasks.generateDialectReport
|
||||
tasks.renderOrmReports.dependsOn task
|
||||
inputs.property "version", project.ormVersion
|
||||
|
||||
sourceDir = layout.buildDirectory.dir('orm/reports')
|
||||
sources {
|
||||
include 'dialect.adoc'
|
||||
}
|
||||
|
||||
outputDir = project.layout.buildDirectory.dir('asciidoc/dialect')
|
||||
|
||||
attributes linkcss: true,
|
||||
stylesheet: "css/hibernate.css"
|
||||
|
||||
resources {
|
||||
from('src/main/style/asciidoctor') {
|
||||
include 'images/**'
|
||||
}
|
||||
from('src/main/style/asciidoctor') {
|
||||
include 'css/**'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -130,6 +130,11 @@ public class DerbyDialect extends Dialect {
|
|||
super(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DatabaseVersion getMinimumSupportedVersion() {
|
||||
return MINIMUM_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnType(int sqlTypeCode) {
|
||||
switch ( sqlTypeCode ) {
|
||||
|
|
|
@ -74,7 +74,6 @@ import org.hibernate.type.descriptor.jdbc.TimeUtcAsJdbcTimeJdbcType;
|
|||
import org.hibernate.type.descriptor.jdbc.TimestampUtcAsInstantJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.TimeUtcAsOffsetTimeJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.TimestampWithTimeZoneJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.UUIDJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
|
||||
|
@ -139,6 +138,9 @@ public class H2Dialect extends Dialect {
|
|||
this( MINIMUM_VERSION );
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println( new H2Dialect().getMinimumSupportedVersion() );
|
||||
}
|
||||
public H2Dialect(DatabaseVersion version) {
|
||||
super(version);
|
||||
|
||||
|
@ -177,6 +179,11 @@ public class H2Dialect extends Dialect {
|
|||
return bits.length > 2 ? Integer.parseInt( bits[2] ) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DatabaseVersion getMinimumSupportedVersion() {
|
||||
return MINIMUM_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getDefaultNonContextualLobCreation() {
|
||||
// http://code.google.com/p/h2database/issues/detail?id=235
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||
*/
|
||||
package org.hibernate.orm.post;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.SourceSetContainer;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
import org.hibernate.orm.env.HibernateVersion;
|
||||
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.Index;
|
||||
|
||||
/**
|
||||
* Generates a report on Dialect information
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class DialectReportTask extends AbstractJandexAwareTask {
|
||||
|
||||
@Inject
|
||||
public DialectReportTask(IndexManager indexManager, Project project) {
|
||||
super(
|
||||
indexManager,
|
||||
project.getLayout().getBuildDirectory().file( "orm/reports/dialect.adoc" )
|
||||
);
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void generateDialectReport() {
|
||||
// the ones we want are all in the hibernate-core project
|
||||
final Project coreProject = getProject().getRootProject().project( "hibernate-core" );
|
||||
final SourceSetContainer sourceSets = coreProject.getExtensions().getByType( SourceSetContainer.class );
|
||||
final SourceSet sourceSet = sourceSets.getByName( SourceSet.MAIN_SOURCE_SET_NAME );
|
||||
final ClassLoader classLoader = Helper.asClassLoader( sourceSet, coreProject.getConfigurations().getByName( "testRuntimeClasspath" ) );
|
||||
|
||||
final DialectClassDelegate dialectClassDelegate = new DialectClassDelegate( classLoader );
|
||||
|
||||
final Index index = getIndexManager().getIndex();
|
||||
final Collection<ClassInfo> allDialectClasses = index.getAllKnownSubclasses( DialectClassDelegate.DIALECT_CLASS_NAME );
|
||||
if ( allDialectClasses.isEmpty() ) {
|
||||
throw new RuntimeException( "Unable to find Dialects" );
|
||||
}
|
||||
|
||||
final List<DialectDelegate> dialectDelegates = collectDialectInfo( dialectClassDelegate, allDialectClasses );
|
||||
generateReport( dialectDelegates );
|
||||
}
|
||||
|
||||
private List<DialectDelegate> collectDialectInfo(
|
||||
DialectClassDelegate dialectClassDelegate,
|
||||
Collection<ClassInfo> allDialectClasses) {
|
||||
final List<DialectDelegate> results = new ArrayList<>();
|
||||
|
||||
allDialectClasses.forEach( (dialectImplClassInfo) -> {
|
||||
final String dialectImplClassName = dialectImplClassInfo.name().toString();
|
||||
final DialectDelegate dialectDelegate = dialectClassDelegate.createDialectDelegate( dialectImplClassName );
|
||||
if ( dialectDelegate == null ) {
|
||||
return;
|
||||
}
|
||||
results.add( dialectDelegate );
|
||||
} );
|
||||
|
||||
results.sort( Comparator.comparing( DialectDelegate::getSimpleName ) );
|
||||
return results;
|
||||
}
|
||||
|
||||
private void generateReport(List<DialectDelegate> dialectDelegates) {
|
||||
final File reportFile = prepareReportFile();
|
||||
try ( final OutputStreamWriter fileWriter = new OutputStreamWriter( new FileOutputStream( reportFile ) ) ) {
|
||||
writeDialectReport( dialectDelegates, fileWriter );
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
throw new RuntimeException( "Should never happen" );
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException( "Error writing to report file", e );
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDialectReport(
|
||||
List<DialectDelegate> dialectDelegates,
|
||||
OutputStreamWriter fileWriter) {
|
||||
writeDialectReportHeader( fileWriter );
|
||||
|
||||
dialectDelegates.forEach( (dialectDelegate) -> writeDialectReportEntry( dialectDelegate, fileWriter ) );
|
||||
|
||||
writeDialectReportFooter( fileWriter );
|
||||
|
||||
}
|
||||
|
||||
private void writeDialectReportHeader(OutputStreamWriter fileWriter) {
|
||||
try {
|
||||
fileWriter.write( "= Supported Dialects\n\n" );
|
||||
fileWriter.write( "Supported Dialects along with the minimum supported version of the underlying database.\n\n\n" );
|
||||
|
||||
HibernateVersion ormVersion = (HibernateVersion) getProject().getRootProject().getExtensions().getByName( "ormVersion" );
|
||||
fileWriter.write( "NOTE: Hibernate version " + ormVersion.getFamily() + "\n\n" );
|
||||
|
||||
fileWriter.write( "[cols=\"a,a\", options=\"header\"]\n" );
|
||||
fileWriter.write( "|===\n" );
|
||||
fileWriter.write( "|Dialect |Minimum Database Version\n" );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException( "Error writing report header", e );
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDialectReportEntry(DialectDelegate dialectDelegate, OutputStreamWriter fileWriter) {
|
||||
try {
|
||||
final String version = dialectDelegate.getMinimumVersion();
|
||||
fileWriter.write( '|' );
|
||||
fileWriter.write( dialectDelegate.getDialectImplClass().getSimpleName() );
|
||||
fileWriter.write( '|' );
|
||||
fileWriter.write( version );
|
||||
fileWriter.write( "\n" );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException( "Unable to access Dialect : " + dialectDelegate.getDialectReference(), e );
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDialectReportFooter(OutputStreamWriter fileWriter) {
|
||||
try {
|
||||
fileWriter.write( "|===\n" );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException( "Error writing report footer", e );
|
||||
}
|
||||
}
|
||||
|
||||
private class DialectClassDelegate {
|
||||
public static final String DIALECT_CLASS_NAME = "org.hibernate.dialect.Dialect";
|
||||
public static final String MIN_VERSION_METHOD_NAME = "getMinimumSupportedVersion";
|
||||
|
||||
private final Class<?> loadedDialectClass;
|
||||
private final Method versionMethod;
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public DialectClassDelegate(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
try {
|
||||
loadedDialectClass = classLoader.loadClass( DIALECT_CLASS_NAME );
|
||||
versionMethod = loadedDialectClass.getDeclaredMethod( MIN_VERSION_METHOD_NAME );
|
||||
versionMethod.setAccessible( true );
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException( "Could not load " + DIALECT_CLASS_NAME, e );
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException( "Could not locate method " + MIN_VERSION_METHOD_NAME, e );
|
||||
}
|
||||
}
|
||||
|
||||
public DialectDelegate createDialectDelegate(String dialectImplClassName) {
|
||||
if ( dialectImplClassName.endsWith( "DialectDelegateWrapper" ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
final Class<?> dialectImplClass;
|
||||
try {
|
||||
dialectImplClass = classLoader.loadClass( dialectImplClassName );
|
||||
}
|
||||
catch (Exception e) {
|
||||
// assume it is from project other than hibernate-core
|
||||
getLogger().debug( "Skipping Dialect " + dialectImplClassName + " - could not instantiate", e );
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( Modifier.isAbstract( dialectImplClass.getModifiers() ) ) {
|
||||
getLogger().debug( "Skipping Dialect " + dialectImplClassName + " - abstract" );
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( dialectImplClass.isAnnotationPresent( Deprecated.class ) ) {
|
||||
getLogger().debug( "Skipping Dialect " + dialectImplClassName + " - deprecated" );
|
||||
return null;
|
||||
}
|
||||
|
||||
return DialectDelegate.from( dialectImplClass, this );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException( "Unable to access Dialect class : " + dialectImplClassName, e );
|
||||
}
|
||||
}
|
||||
|
||||
public Class<?> getLoadedDialectClass() {
|
||||
return loadedDialectClass;
|
||||
}
|
||||
|
||||
public Method getVersionMethod() {
|
||||
return versionMethod;
|
||||
}
|
||||
}
|
||||
|
||||
private static class DialectDelegate {
|
||||
private final Class<?> dialectImplClass;
|
||||
private final DialectClassDelegate dialectClassDelegate;
|
||||
|
||||
private final Object dialectRef;
|
||||
|
||||
public static DialectDelegate from(Class<?> dialectImplClass, DialectClassDelegate dialectClassDelegate) {
|
||||
return new DialectDelegate( dialectImplClass, dialectClassDelegate );
|
||||
}
|
||||
|
||||
public DialectDelegate(Class<?> dialectImplClass, DialectClassDelegate dialectClassDelegate) {
|
||||
this.dialectImplClass = dialectImplClass;
|
||||
this.dialectClassDelegate = dialectClassDelegate;
|
||||
try {
|
||||
this.dialectRef = dialectImplClass.getConstructor().newInstance();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException( "Unable to create DialectDelegate for " + dialectImplClass.getName(), e );
|
||||
}
|
||||
}
|
||||
|
||||
public String getSimpleName() {
|
||||
return dialectImplClass.getSimpleName();
|
||||
}
|
||||
|
||||
public DialectClassDelegate getDialectClassDelegate() {
|
||||
return dialectClassDelegate;
|
||||
}
|
||||
|
||||
public Class<?> getDialectImplClass() {
|
||||
return dialectImplClass;
|
||||
}
|
||||
|
||||
public Object getDialectReference() {
|
||||
return dialectRef;
|
||||
}
|
||||
|
||||
public String getMinimumVersion() {
|
||||
try {
|
||||
final Object versionRef = dialectClassDelegate.getVersionMethod().invoke( dialectRef );
|
||||
return versionRef.toString();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException( "Unable to access " + DialectClassDelegate.MIN_VERSION_METHOD_NAME + " for " + dialectClassDelegate.loadedDialectClass.getName(), e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||
*/
|
||||
package org.hibernate.orm.post;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.file.Directory;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Helper {
|
||||
public static ClassLoader asClassLoader(SourceSet sourceSet, Configuration gradleClasspath) {
|
||||
final List<URL> urls = new ArrayList<>();
|
||||
|
||||
final Directory classesDirectory = sourceSet.getJava().getClassesDirectory().get();
|
||||
final File classesDir = classesDirectory.getAsFile();
|
||||
addElement( urls, classesDir );
|
||||
|
||||
for ( File dependencyFile : gradleClasspath.resolve() ) {
|
||||
addElement( urls, dependencyFile );
|
||||
}
|
||||
|
||||
return new URLClassLoader( urls.toArray( new URL[0] ) );
|
||||
}
|
||||
|
||||
private static void addElement(List<URL> urls, File element) {
|
||||
try {
|
||||
urls.add( element.toURI().toURL() );
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
throw new RuntimeException( "Unable to create URL for ClassLoader: " + element.getAbsolutePath(), e );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -66,5 +66,13 @@ public class ReportGenerationPlugin implements Plugin<Project> {
|
|||
);
|
||||
loggingTask.dependsOn( indexerTask );
|
||||
groupingTask.dependsOn( loggingTask );
|
||||
|
||||
final DialectReportTask dialectTask = project.getTasks().create(
|
||||
"generateDialectReport",
|
||||
DialectReportTask.class,
|
||||
indexManager
|
||||
);
|
||||
dialectTask.dependsOn( indexerTask );
|
||||
groupingTask.dependsOn( dialectTask );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue