use of org.gradle.api.publish.PublishingExtension in project rest.li by linkedin.
the class PegasusPlugin method configureDataTemplateGeneration.
@SuppressWarnings("deprecation")
protected GenerateDataTemplateTask configureDataTemplateGeneration(Project project, SourceSet sourceSet) {
File dataSchemaDir = project.file(getDataSchemaPath(project, sourceSet));
File generatedDataTemplateDir = project.file(getGeneratedDirPath(project, sourceSet, DATA_TEMPLATE_GEN_TYPE) + File.separatorChar + "java");
File publishableSchemasBuildDir = project.file(project.getBuildDir().getAbsolutePath() + File.separatorChar + sourceSet.getName() + "Schemas");
File publishableLegacySchemasBuildDir = project.file(project.getBuildDir().getAbsolutePath() + File.separatorChar + sourceSet.getName() + "LegacySchemas");
File publishableExtensionSchemasBuildDir = project.file(project.getBuildDir().getAbsolutePath() + File.separatorChar + sourceSet.getName() + "ExtensionSchemas");
// generate data template source files from data schema
GenerateDataTemplateTask generateDataTemplatesTask = project.getTasks().create(sourceSet.getTaskName("generate", "dataTemplate"), GenerateDataTemplateTask.class, task -> {
task.setInputDir(dataSchemaDir);
task.setDestinationDir(generatedDataTemplateDir);
task.setResolverPath(getDataModelConfig(project, sourceSet));
task.setCodegenClasspath(project.getConfigurations().getByName(PEGASUS_PLUGIN_CONFIGURATION));
if (isPropertyTrue(project, ENABLE_ARG_FILE)) {
task.setEnableArgFile(true);
}
if (isPropertyTrue(project, CODE_GEN_PATH_CASE_SENSITIVE)) {
task.setGenerateLowercasePath(false);
}
task.onlyIf(t -> {
if (task.getInputDir().exists()) {
@SuppressWarnings("unchecked") Map<String, PegasusOptions> pegasusOptions = (Map<String, PegasusOptions>) project.getExtensions().getExtraProperties().get("pegasus");
return pegasusOptions.get(sourceSet.getName()).hasGenerationMode(PegasusOptions.GenerationMode.PEGASUS);
}
return false;
});
task.doFirst(new CacheableAction<>(t -> deleteGeneratedDir(project, sourceSet, DATA_TEMPLATE_GEN_TYPE)));
});
// TODO: Tighten the types so that _generateSourcesJarTask must be of type Jar.
((Jar) _generateSourcesJarTask).from(generateDataTemplatesTask.getDestinationDir());
_generateSourcesJarTask.dependsOn(generateDataTemplatesTask);
_generateJavadocTask.source(generateDataTemplatesTask.getDestinationDir());
_generateJavadocTask.setClasspath(_generateJavadocTask.getClasspath().plus(project.getConfigurations().getByName("dataTemplateCompile")).plus(generateDataTemplatesTask.getResolverPath()));
_generateJavadocTask.dependsOn(generateDataTemplatesTask);
// Add extra dependencies for data model compilation
project.getDependencies().add("dataTemplateCompile", "com.google.code.findbugs:jsr305:3.0.2");
// create new source set for generated java source and class files
String targetSourceSetName = getGeneratedSourceSetName(sourceSet, DATA_TEMPLATE_GEN_TYPE);
SourceSetContainer sourceSets = project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets();
SourceSet targetSourceSet = sourceSets.create(targetSourceSetName, ss -> {
ss.java(sourceDirectorySet -> sourceDirectorySet.srcDir(generatedDataTemplateDir));
ss.setCompileClasspath(getDataModelConfig(project, sourceSet).plus(project.getConfigurations().getByName("dataTemplateCompile")));
});
// idea plugin needs to know about new generated java source directory and its dependencies
addGeneratedDir(project, targetSourceSet, Arrays.asList(getDataModelConfig(project, sourceSet), project.getConfigurations().getByName("dataTemplateCompile")));
// Set source compatibility to 1.8 as the data-templates now generate code with Java 8 features.
JavaCompile compileTask = project.getTasks().withType(JavaCompile.class).getByName(targetSourceSet.getCompileJavaTaskName());
compileTask.doFirst(new CacheableAction<>(task -> {
((JavaCompile) task).setSourceCompatibility("1.8");
((JavaCompile) task).setTargetCompatibility("1.8");
}));
// make sure that java source files have been generated before compiling them
compileTask.dependsOn(generateDataTemplatesTask);
// Dummy task to maintain backward compatibility
// TODO: Delete this task once use cases have had time to reference the new task
Task destroyStaleFiles = project.getTasks().create(sourceSet.getName() + "DestroyStaleFiles", Delete.class);
destroyStaleFiles.onlyIf(task -> {
project.getLogger().lifecycle("{} task is a NO-OP task.", task.getPath());
return false;
});
// Dummy task to maintain backward compatibility, as this task was replaced by CopySchemas
// TODO: Delete this task once use cases have had time to reference the new task
Task copyPdscSchemasTask = project.getTasks().create(sourceSet.getName() + "CopyPdscSchemas", Copy.class);
copyPdscSchemasTask.dependsOn(destroyStaleFiles);
copyPdscSchemasTask.onlyIf(task -> {
project.getLogger().lifecycle("{} task is a NO-OP task.", task.getPath());
return false;
});
// Prepare schema files for publication by syncing schema folders.
Task prepareSchemasForPublishTask = project.getTasks().create(sourceSet.getName() + "CopySchemas", Sync.class, task -> {
task.from(dataSchemaDir, syncSpec -> DATA_TEMPLATE_FILE_SUFFIXES.forEach(suffix -> syncSpec.include("**/*" + suffix)));
task.into(publishableSchemasBuildDir);
});
prepareSchemasForPublishTask.dependsOn(copyPdscSchemasTask);
Collection<Task> dataTemplateJarDepends = new ArrayList<>();
dataTemplateJarDepends.add(compileTask);
dataTemplateJarDepends.add(prepareSchemasForPublishTask);
// Convert all PDL files back to PDSC for publication
// TODO: Remove this conversion permanently once translated PDSCs are no longer needed.
Task prepareLegacySchemasForPublishTask = project.getTasks().create(sourceSet.getName() + "TranslateSchemas", TranslateSchemasTask.class, task -> {
task.setInputDir(dataSchemaDir);
task.setDestinationDir(publishableLegacySchemasBuildDir);
task.setResolverPath(getDataModelConfig(project, sourceSet));
task.setCodegenClasspath(project.getConfigurations().getByName(PEGASUS_PLUGIN_CONFIGURATION));
task.setSourceFormat(SchemaFileType.PDL);
task.setDestinationFormat(SchemaFileType.PDSC);
task.setKeepOriginal(true);
task.setSkipVerification(true);
if (isPropertyTrue(project, ENABLE_ARG_FILE)) {
task.setEnableArgFile(true);
}
});
prepareLegacySchemasForPublishTask.dependsOn(destroyStaleFiles);
dataTemplateJarDepends.add(prepareLegacySchemasForPublishTask);
// extension schema directory
File extensionSchemaDir = project.file(getExtensionSchemaPath(project, sourceSet));
if (!SharedFileUtils.getSuffixedFiles(project, extensionSchemaDir, PDL_FILE_SUFFIX).isEmpty()) {
// Validate extension schemas if extension schemas are provided.
ValidateExtensionSchemaTask validateExtensionSchemaTask = project.getTasks().create(sourceSet.getTaskName("validate", "ExtensionSchemas"), ValidateExtensionSchemaTask.class, task -> {
task.setInputDir(extensionSchemaDir);
task.setResolverPath(getDataModelConfig(project, sourceSet).plus(project.files(getDataSchemaPath(project, sourceSet))));
task.setClassPath(project.getConfigurations().getByName(PEGASUS_PLUGIN_CONFIGURATION));
if (isPropertyTrue(project, ENABLE_ARG_FILE)) {
task.setEnableArgFile(true);
}
});
Task prepareExtensionSchemasForPublishTask = project.getTasks().create(sourceSet.getName() + "CopyExtensionSchemas", Sync.class, task -> {
task.from(extensionSchemaDir, syncSpec -> syncSpec.include("**/*" + PDL_FILE_SUFFIX));
task.into(publishableExtensionSchemasBuildDir);
});
prepareExtensionSchemasForPublishTask.dependsOn(validateExtensionSchemaTask);
prepareExtensionSchemasForPublishTask.dependsOn(copyPdscSchemasTask);
dataTemplateJarDepends.add(prepareExtensionSchemasForPublishTask);
}
// include pegasus files in the output of this SourceSet
project.getTasks().withType(ProcessResources.class).getByName(targetSourceSet.getProcessResourcesTaskName(), it -> {
it.from(prepareSchemasForPublishTask, copy -> copy.into("pegasus"));
// TODO: Remove this permanently once translated PDSCs are no longer needed.
it.from(prepareLegacySchemasForPublishTask, copy -> copy.into(TRANSLATED_SCHEMAS_DIR));
Sync copyExtensionSchemasTask = project.getTasks().withType(Sync.class).findByName(sourceSet.getName() + "CopyExtensionSchemas");
if (copyExtensionSchemasTask != null) {
it.from(copyExtensionSchemasTask, copy -> copy.into("extensions"));
}
});
// create data template jar file
Jar dataTemplateJarTask = project.getTasks().create(sourceSet.getName() + "DataTemplateJar", Jar.class, task -> {
task.dependsOn(dataTemplateJarDepends);
task.from(targetSourceSet.getOutput());
// FIXME change to #getArchiveAppendix().set(...); breaks backwards-compatibility before 5.1
task.setAppendix(getAppendix(sourceSet, "data-template"));
task.setDescription("Generate a data template jar");
});
// add the data model and date template jars to the list of project artifacts.
if (!isTestSourceSet(sourceSet)) {
project.getArtifacts().add("dataTemplate", dataTemplateJarTask);
} else {
project.getArtifacts().add("testDataTemplate", dataTemplateJarTask);
}
// include additional dependencies into the appropriate configuration used to compile the input source set
// must include the generated data template classes and their dependencies the configuration
String compileConfigName = isTestSourceSet(sourceSet) ? "testCompile" : "compile";
Configuration compileConfig = project.getConfigurations().maybeCreate(compileConfigName);
compileConfig.extendsFrom(getDataModelConfig(project, sourceSet), project.getConfigurations().getByName("dataTemplateCompile"));
// FIXME change to #getArchiveFile(); breaks backwards-compatibility before 5.1
project.getDependencies().add(compileConfigName, project.files(dataTemplateJarTask.getArchivePath()));
// The below Action is only applied when the 'ivy-publish' is applied by the consumer.
// If the consumer does not use ivy-publish, this is a noop.
// this Action prepares the project applying the pegasus plugin to publish artifacts using these steps:
// 1. Registers "feature variants" for pegasus-specific artifacts;
// see https://docs.gradle.org/6.1/userguide/feature_variants.html
// 2. Wires legacy configurations like `dataTemplateCompile` to auto-generated feature variant *Api and
// *Implementation configurations for backwards compatibility.
// 3. Configures the Ivy Publication to include auto-generated feature variant *Api and *Implementation
// configurations and their dependencies.
project.getPlugins().withType(IvyPublishPlugin.class, ivyPublish -> {
if (!isAtLeastGradle61()) {
throw new GradleException("Using the ivy-publish plugin with the pegasus plugin requires Gradle 6.1 or higher " + "at build time. Please upgrade.");
}
JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class);
// create new capabilities per source set; automatically creates api and implementation configurations
String featureName = mapSourceSetToFeatureName(targetSourceSet);
try {
/*
reflection is required to preserve compatibility with Gradle 5.2.1 and below
TODO once Gradle 5.3+ is required, remove reflection and replace with:
java.registerFeature(featureName, featureSpec -> {
featureSpec.usingSourceSet(targetSourceSet);
});
*/
Method registerFeature = JavaPluginExtension.class.getDeclaredMethod("registerFeature", String.class, Action.class);
Action<?> /*<org.gradle.api.plugins.FeatureSpec>*/
featureSpecAction = createFeatureVariantFromSourceSet(targetSourceSet);
registerFeature.invoke(java, featureName, featureSpecAction);
} catch (ReflectiveOperationException e) {
throw new GradleException("Unable to register new feature variant", e);
}
// expose transitive dependencies to consumers via variant configurations
Configuration featureConfiguration = project.getConfigurations().getByName(featureName);
Configuration mainGeneratedDataTemplateApi = project.getConfigurations().getByName(targetSourceSet.getApiConfigurationName());
featureConfiguration.extendsFrom(mainGeneratedDataTemplateApi);
mainGeneratedDataTemplateApi.extendsFrom(getDataModelConfig(project, targetSourceSet), project.getConfigurations().getByName("dataTemplateCompile"));
// Configure the existing IvyPublication
// For backwards-compatibility, make the legacy dataTemplate/testDataTemplate configurations extend
// their replacements, auto-created when we registered the new feature variant
project.afterEvaluate(p -> {
PublishingExtension publishing = p.getExtensions().getByType(PublishingExtension.class);
// When configuring a Gradle Publication, use this value to find the name of the publication to configure. Defaults to "ivy".
String publicationName = p.getExtensions().getExtraProperties().getProperties().getOrDefault("PegasusPublicationName", "ivy").toString();
IvyPublication ivyPublication = publishing.getPublications().withType(IvyPublication.class).getByName(publicationName);
ivyPublication.configurations(configurations -> configurations.create(featureName, legacyConfiguration -> {
legacyConfiguration.extend(p.getConfigurations().getByName(targetSourceSet.getApiElementsConfigurationName()).getName());
legacyConfiguration.extend(p.getConfigurations().getByName(targetSourceSet.getRuntimeElementsConfigurationName()).getName());
}));
});
});
if (debug) {
System.out.println("configureDataTemplateGeneration sourceSet " + sourceSet.getName());
System.out.println(compileConfigName + ".allDependencies : " + project.getConfigurations().getByName(compileConfigName).getAllDependencies());
System.out.println(compileConfigName + ".extendsFrom: " + project.getConfigurations().getByName(compileConfigName).getExtendsFrom());
System.out.println(compileConfigName + ".transitive: " + project.getConfigurations().getByName(compileConfigName).isTransitive());
}
project.getTasks().getByName(sourceSet.getCompileJavaTaskName()).dependsOn(dataTemplateJarTask);
return generateDataTemplatesTask;
}
Aggregations