Author: steve.ebersole(a)jboss.com
Date: 2010-06-28 15:43:57 -0400 (Mon, 28 Jun 2010)
New Revision: 19845
Added:
core/branches/gradle2/buildSrc/src/main/java/org/hibernate/gradle/testing/database/IvyXmlDependency.java
Modified:
core/branches/gradle2/buildSrc/src/main/java/org/hibernate/gradle/testing/database/DatabaseMatrixPlugin.java
Log:
allow matrix.gradle file to define database testing dependencies
Modified:
core/branches/gradle2/buildSrc/src/main/java/org/hibernate/gradle/testing/database/DatabaseMatrixPlugin.java
===================================================================
---
core/branches/gradle2/buildSrc/src/main/java/org/hibernate/gradle/testing/database/DatabaseMatrixPlugin.java 2010-06-28
18:47:57 UTC (rev 19844)
+++
core/branches/gradle2/buildSrc/src/main/java/org/hibernate/gradle/testing/database/DatabaseMatrixPlugin.java 2010-06-28
19:43:57 UTC (rev 19845)
@@ -2,12 +2,13 @@
import java.io.File;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import groovy.lang.Closure;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
-import org.gradle.api.file.FileCollection;
import org.gradle.api.internal.artifacts.dependencies.DefaultSelfResolvingDependency;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,10 +48,57 @@
}
}
+ private static final String MATRIX_NODE_CONVENTION_KEY = "matrixNode";
+ private static final String MATRIX_BUILD_FILE = "matrix.gradle";
+ private static final String IVY_XML_FILE = "ivy.xml";
+
private void applyPossibleDatabaseDirectory(final File databaseDir) {
final String databaseName = databaseDir.getName();
log.debug( "Checking potential database directory : {}", databaseName );
+ MatrixNode node = null;
+
+ // 3 types of support here:
+ // 1) directory contains a file named 'matrix.gradle'
+ // 2) directory contains a file named 'ivy.xml'
+ // 3) directory contains a sub-directory named 'jdbc' containing the driver
artifacts
+
+ final File matrixFile = new File( databaseDir, MATRIX_BUILD_FILE );
+ if ( matrixFile.exists() && matrixFile.isFile() ) {
+ // (1) we found the 'matrix.gradle' file
+ node = prepareFromGradleFile( matrixFile );
+ }
+ else {
+ final File ivyXmlFile = new File( databaseDir, IVY_XML_FILE );
+ if ( ivyXmlFile.exists() && ivyXmlFile.isFile() ) {
+ // (2) we found the 'ivy.xml' file
+ node = prepareFromIvyXmlFile( ivyXmlFile );
+ }
+ else {
+ final File jdbcDir = new File( databaseDir, "jdbc" );
+ if ( jdbcDir.exists() && jdbcDir.isDirectory() ) {
+ node = prepareFromJdbcDir( jdbcDir );
+ }
+ }
+ }
+
+ if ( node == null ) {
+ log.info( "" );
+ return;
+ }
+
+ final File resourcesDir = new File( matrixFile.getParentFile(), "resources"
);
+ if ( resourcesDir.isDirectory() && resourcesDir.exists() ) {
+ node.getTestingRuntimeConfiguration().addDependency(
+ new DefaultSelfResolvingDependency( project.files( resourcesDir ) )
+ );
+ }
+
+ matrixNodes.add( node );
+
+
+
+
final Configuration configuration = prepareJdbcDependencies( databaseDir );
if ( configuration == null ) {
return;
@@ -58,28 +106,128 @@
configuration.setVisible( true );
configuration.setDescription( "The [" + databaseName + "] JDBC
dependency configuration" );
- final File resourcesDir = new File( databaseDir, "resources" );
- if ( resourcesDir.isDirectory() && resourcesDir.exists() ) {
- configuration.addDependency(
- new DefaultSelfResolvingDependency( project.files( resourcesDir ) )
+
+ }
+
+ private MatrixNode prepareFromGradleFile(File matrixFile) {
+ MatrixDotGradleMatrixNodeImpl matrixNode = new MatrixDotGradleMatrixNodeImpl(
matrixFile.getParentFile().getName() );
+ MatrixDotGradleMatrixNodeConvention convention = new
MatrixDotGradleMatrixNodeConvention( matrixNode );
+ project.getConvention().getPlugins().put( MATRIX_NODE_CONVENTION_KEY, convention );
+ try {
+ project.apply( Collections.singletonMap( "from", matrixFile ) );
+ }
+ finally {
+ project.getConvention().getPlugins().remove( MATRIX_NODE_CONVENTION_KEY );
+ }
+ return matrixNode;
+ }
+
+ /**
+ * {@link MatrixNode} implementation for handling 'matrix.gradle' files
+ */
+ private class MatrixDotGradleMatrixNodeImpl implements MatrixNode {
+ private final String name;
+ private final Configuration jdbcDependencies;
+ private Jdk jdk;
+
+ public MatrixDotGradleMatrixNodeImpl(String name) {
+ this.name = name;
+ this.jdbcDependencies = prepareConfiguration( name );
+ this.jdk = getDefaultJdk();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Configuration getTestingRuntimeConfiguration() {
+ return jdbcDependencies;
+ }
+
+ public Jdk getTestingRuntimeJdk() {
+ return jdk;
+ }
+ }
+
+ /**
+ * Provides simplified convention object to the database-specific script for convenient
configuration.
+ */
+ private class MatrixDotGradleMatrixNodeConvention {
+ private final MatrixDotGradleMatrixNodeImpl matrixNode;
+
+ private MatrixDotGradleMatrixNodeConvention(MatrixDotGradleMatrixNodeImpl matrixNode)
{
+ this.matrixNode = matrixNode;
+ }
+
+ public void jdbcDependency(Object dependencyNotation, Closure closure) {
+ project.getDependencies().add( matrixNode.jdbcDependencies.getName(),
dependencyNotation, closure );
+ }
+
+ public void jdbcDependency(Object dependencyNotation) {
+ project.getDependencies().add( matrixNode.jdbcDependencies.getName(),
dependencyNotation );
+ }
+
+ public void jdk(Jdk jdk) {
+ matrixNode.jdk = jdk;
+ }
+ }
+
+ private MatrixNode prepareFromIvyXmlFile(File ivyXmlFile) {
+ return new IvyXmlMatrixNode( ivyXmlFile );
+ }
+
+ private class IvyXmlMatrixNode implements MatrixNode {
+ private final String name;
+ private final Configuration jdbcDependencies;
+ private final Jdk jdk = getDefaultJdk();
+
+ private IvyXmlMatrixNode(File ivyXmlFile) {
+ name = ivyXmlFile.getParentFile().getName();
+ jdbcDependencies = getOrCreateConfiguration( name );
+ jdbcDependencies.addDependency( new IvyXmlDependency( project, ivyXmlFile ) );
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Configuration getTestingRuntimeConfiguration() {
+ return jdbcDependencies;
+ }
+
+ public Jdk getTestingRuntimeJdk() {
+ return jdk;
+ }
+ }
+
+ private MatrixNode prepareFromJdbcDir(File jdbcDir) {
+ return new LocalMatrixNode( jdbcDir );
+ }
+
+ private class LocalMatrixNode implements MatrixNode {
+ private final String name;
+ private final Configuration jdbcDependencies;
+ private final Jdk jdk = getDefaultJdk();
+
+ private LocalMatrixNode(File jdbcDir) {
+ name = jdbcDir.getParentFile().getName();
+ jdbcDependencies = getOrCreateConfiguration( name );
+ jdbcDependencies.addDependency(
+ new DefaultSelfResolvingDependency( project.files( (File[]) jdbcDir.listFiles() ) )
);
}
- matrixNodes.add(
- new MatrixNode() {
- public String getName() {
- return databaseName;
- }
+ public String getName() {
+ return name;
+ }
- public Configuration getTestingRuntimeConfiguration() {
- return configuration;
- }
+ public Configuration getTestingRuntimeConfiguration() {
+ return jdbcDependencies;
+ }
- public Jdk getTestingRuntimeJdk() {
- return null;
- }
- }
- );
+ public Jdk getTestingRuntimeJdk() {
+ return jdk;
+ }
}
private Configuration prepareJdbcDependencies(File databaseDir) {
@@ -125,4 +273,23 @@
public List<MatrixNode> getMatrixNodes() {
return matrixNodes;
}
+
+ private Configuration prepareConfiguration(String name) {
+ Configuration configuration = getOrCreateConfiguration( name );
+ configuration.setVisible( true );
+ configuration.setDescription( "The [" + name + "] JDBC dependency
configuration" );
+ return configuration;
+ }
+
+ private Configuration getOrCreateConfiguration(String configurationName) {
+ Configuration configuration = project.getConfigurations().findByName( configurationName
);
+ if ( configuration == null ) {
+ configuration = project.getConfigurations().add( configurationName );
+ }
+ return configuration;
+ }
+
+ private Jdk getDefaultJdk() {
+ return (Jdk) project.getProperties().get( "java5Home" );
+ }
}
Added:
core/branches/gradle2/buildSrc/src/main/java/org/hibernate/gradle/testing/database/IvyXmlDependency.java
===================================================================
---
core/branches/gradle2/buildSrc/src/main/java/org/hibernate/gradle/testing/database/IvyXmlDependency.java
(rev 0)
+++
core/branches/gradle2/buildSrc/src/main/java/org/hibernate/gradle/testing/database/IvyXmlDependency.java 2010-06-28
19:43:57 UTC (rev 19845)
@@ -0,0 +1,194 @@
+package org.hibernate.gradle.testing.database;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ivy.Ivy;
+import org.apache.ivy.core.cache.DefaultRepositoryCacheManager;
+import org.apache.ivy.core.cache.RepositoryCacheManager;
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.report.ResolveReport;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.repositories.InternalRepository;
+import org.gradle.api.internal.artifacts.IvyService;
+import org.gradle.api.internal.artifacts.configurations.DefaultConfigurationContainer;
+import org.gradle.api.internal.artifacts.configurations.ResolverProvider;
+import org.gradle.api.internal.artifacts.dependencies.DefaultSelfResolvingDependency;
+import org.gradle.api.internal.artifacts.ivyservice.DefaultIvyService;
+import org.gradle.api.internal.artifacts.ivyservice.ErrorHandlingIvyService;
+import org.gradle.api.internal.artifacts.ivyservice.IvyFactory;
+import org.gradle.api.internal.artifacts.ivyservice.SettingsConverter;
+import org.gradle.api.internal.artifacts.ivyservice.ShortcircuitEmptyConfigsIvyService;
+import org.gradle.api.internal.file.AbstractFileCollection;
+import org.gradle.invocation.DefaultGradle;
+
+import org.hibernate.gradle.util.BuildException;
+import org.hibernate.gradle.util.ResolutionException;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class IvyXmlDependency extends DefaultSelfResolvingDependency {
+ private final String name;
+
+ public IvyXmlDependency(Project project, File ivyXmlFile) {
+ super( new IvyXmlDependencyFileCollection( project, ivyXmlFile ) );
+ this.name = ivyXmlFile.getParentFile().getName() + '/' + ivyXmlFile.getName();
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public IvyXmlDependencyFileCollection getSource() {
+ return (IvyXmlDependencyFileCollection) super.getSource();
+ }
+
+ private static class IvyXmlDependencyFileCollection extends AbstractFileCollection {
+ private final Project project;
+ private final File ivyXmlFile;
+ private Set<File> resolvedDependencyFiles;
+
+ private IvyXmlDependencyFileCollection(Project project, File ivyXmlFile) {
+ this.project = project;
+ this.ivyXmlFile = ivyXmlFile;
+ }
+
+ public File getIvyXmlFile() {
+ return ivyXmlFile;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return ivyXmlFile.getAbsolutePath();
+ }
+
+ public Set<File> getFiles() {
+ if ( resolvedDependencyFiles == null ) {
+ resolvedDependencyFiles = resolveDependencyFiles();
+ }
+ return resolvedDependencyFiles;
+ }
+
+ private Set<File> resolveDependencyFiles() {
+ DefaultIvyService ivyService = unwrap(
+ ( (DefaultConfigurationContainer) project.getConfigurations() ).getIvyService()
+ );
+
+ final ModuleDescriptor moduleDescriptor = resolveIvyXml( ivyService );
+
+ DefaultRepositoryCacheManager repositoryCacheManager = null;
+ final ResolverProvider resolverProvider = ivyService.getResolverProvider();
+ for ( DependencyResolver resolver : resolverProvider.getResolvers() ) {
+ RepositoryCacheManager potentialRepositoryCacheManager =
resolver.getRepositoryCacheManager();
+ if ( DefaultRepositoryCacheManager.class.isInstance( potentialRepositoryCacheManager
) ) {
+ repositoryCacheManager = (DefaultRepositoryCacheManager)
potentialRepositoryCacheManager;
+ }
+ }
+ if ( repositoryCacheManager == null ) {
+ throw buildResolutionException( moduleDescriptor.getModuleRevisionId(), "Unable
to locate proper dependency cache manager" );
+ }
+
+ HashSet<File> dependencyFiles = new HashSet<File>();
+ for ( DependencyDescriptor dependencyDescriptor : moduleDescriptor.getDependencies() )
{
+ final ModuleRevisionId info =
dependencyDescriptor.getDynamicConstraintDependencyRevisionId();
+
+ dependencyFiles.add( repositoryCacheManager.getIvyFileInCache( info ) );
+ }
+
+ return dependencyFiles;
+ }
+
+ private DefaultIvyService unwrap(IvyService ivyService) {
+ if ( DefaultIvyService.class.isInstance( ivyService ) ) {
+ return (DefaultIvyService) ivyService;
+ }
+
+ if ( ErrorHandlingIvyService.class.isInstance( ivyService ) ) {
+ return unwrap( ( (ErrorHandlingIvyService) ivyService ).getIvyService() );
+ }
+
+ if ( ShortcircuitEmptyConfigsIvyService.class.isInstance( ivyService ) ) {
+ return unwrap( ( (ShortcircuitEmptyConfigsIvyService) ivyService ).getIvyService()
);
+ }
+
+ throw new BuildException( "Do not know how to extract needed ivy config from ivy
service of type " + ivyService.getClass().getName() );
+ }
+
+ private ModuleDescriptor resolveIvyXml(DefaultIvyService ivyService) {
+ Ivy ivy = locateIvyService( ivyService );
+ ResolveReport resolveReport = performResolve( ivy, ivyXmlFile );
+ return resolveReport.getModuleDescriptor();
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ private ResolveReport performResolve(Ivy ivy, File ivyXmlFile) {
+ try {
+ ResolveReport resolveReport = ivy.resolve( ivyXmlFile );
+ if ( resolveReport.hasError() ) {
+ throw buildResolutionException(
+ resolveReport.getModuleDescriptor().getModuleRevisionId(),
+ resolveReport.getAllProblemMessages()
+ );
+ }
+ return resolveReport;
+ }
+ catch ( ParseException e ) {
+ throw new BuildException( "Malformed ivy dependency file [" +
ivyXmlFile.getName() + "]", e );
+ }
+ catch ( IOException e ) {
+ throw new BuildException( "Problem reading ivy dependency file [" +
ivyXmlFile.getName() + "]", e );
+ }
+ }
+
+ private Ivy locateIvyService(DefaultIvyService ivyService) {
+ final IvyFactory ivyFactory = ivyService.getIvyFactory();
+ final SettingsConverter settingsConverter = ivyService.getSettingsConverter();
+ final ResolverProvider resolverProvider = ivyService.getResolverProvider();
+
+ // Ugh, can absolutely find no way to access this other than a bunch of recursive
reflection calls to
+ // locate the build's org.gradle.api.internal.project.TopLevelBuildServiceRegistry
and access its
+ // private
org.gradle.api.internal.project.TopLevelBuildServiceRegistry.clientModuleRegistry field.
+ //
+ // Not sure if it is critical to reuse that map instance or not. seems to work
without, but i have no
+ // idea about the ramifications.
+ Map<String, ModuleDescriptor> clientModuleRegistry = new HashMap<String,
ModuleDescriptor>();
+
+ // this part is mainly DefaultIvyService#ivyForResolve
+ IvySettings ivySettings = settingsConverter.convertForResolve(
+ resolverProvider.getResolvers(),
+ project.getGradle().getGradleUserHomeDir(),
+ getGradeService( InternalRepository.class ),
+ clientModuleRegistry
+ );
+ return ivyFactory.createIvy( ivySettings );
+ }
+
+ protected <T> T getGradeService(Class<T> type) {
+ return ( (DefaultGradle) project.getGradle() ).getServiceRegistryFactory().get( type
);
+ }
+ }
+
+ private static ResolutionException buildResolutionException(ModuleRevisionId descriptor,
List<String> messages) {
+ return new ResolutionException( descriptor.toString(), messages );
+ }
+
+ private static ResolutionException buildResolutionException(ModuleRevisionId descriptor,
String... messages) {
+ return buildResolutionException( descriptor, Arrays.asList( messages ) );
+ }
+}
Show replies by date