All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.context.aot.AbstractAotProcessor Maven / Gradle / Ivy

/*
 * Copyright 2002-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.aot;

import java.io.IOException;
import java.nio.file.Path;

import org.springframework.aot.generate.FileSystemGeneratedFiles;
import org.springframework.aot.generate.GeneratedFiles.Kind;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.nativex.FileNativeConfigurationWriter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.FileSystemUtils;

/**
 * Abstract base class for filesystem-based ahead-of-time (AOT) processing.
 *
 * 

Concrete implementations should override {@link #doProcess()} that kicks * off the optimization of the target, usually an application. * * @author Stephane Nicoll * @author Andy Wilkinson * @author Phillip Webb * @author Sam Brannen * @since 6.0 * @param the type of the processing result * @see FileSystemGeneratedFiles * @see FileNativeConfigurationWriter * @see org.springframework.context.aot.ContextAotProcessor * @see org.springframework.test.context.aot.TestAotProcessor */ public abstract class AbstractAotProcessor { /** * The name of a system property that is made available when the processor * runs. * @see #doProcess() */ private static final String AOT_PROCESSING = "spring.aot.processing"; private final Settings settings; /** * Create a new processor instance with the supplied {@linkplain Settings settings}. * @see Settings#builder() */ protected AbstractAotProcessor(Settings settings) { this.settings = settings; } /** * Get the {@linkplain Settings settings} for this AOT processor. */ protected Settings getSettings() { return this.settings; } /** * Run AOT processing. * @return the result of the processing. */ public final T process() { try { System.setProperty(AOT_PROCESSING, "true"); return doProcess(); } finally { System.clearProperty(AOT_PROCESSING); } } protected abstract T doProcess(); /** * Delete the source, resource, and class output directories. */ protected void deleteExistingOutput() { deleteExistingOutput(getSettings().getSourceOutput(), getSettings().getResourceOutput(), getSettings().getClassOutput()); } private void deleteExistingOutput(Path... paths) { for (Path path : paths) { try { FileSystemUtils.deleteRecursively(path); } catch (IOException ex) { throw new RuntimeException("Failed to delete existing output in '" + path + "'"); } } } protected FileSystemGeneratedFiles createFileSystemGeneratedFiles() { return new FileSystemGeneratedFiles(this::getRoot); } private Path getRoot(Kind kind) { return switch (kind) { case SOURCE -> getSettings().getSourceOutput(); case RESOURCE -> getSettings().getResourceOutput(); case CLASS -> getSettings().getClassOutput(); }; } protected void writeHints(RuntimeHints hints) { FileNativeConfigurationWriter writer = new FileNativeConfigurationWriter( getSettings().getResourceOutput(), getSettings().getGroupId(), getSettings().getArtifactId()); writer.write(hints); } /** * Common settings for AOT processors. */ public static final class Settings { private final Path sourceOutput; private final Path resourceOutput; private final Path classOutput; private final String groupId; private final String artifactId; private Settings(Path sourceOutput, Path resourceOutput, Path classOutput, String groupId, String artifactId) { this.sourceOutput = sourceOutput; this.resourceOutput = resourceOutput; this.classOutput = classOutput; this.groupId = groupId; this.artifactId = artifactId; } /** * Create a new {@link Builder} for {@link Settings}. */ public static Builder builder() { return new Builder(); } /** * Get the output directory for generated sources. */ public Path getSourceOutput() { return this.sourceOutput; } /** * Get the output directory for generated resources. */ public Path getResourceOutput() { return this.resourceOutput; } /** * Get the output directory for generated classes. */ public Path getClassOutput() { return this.classOutput; } /** * Get the group ID of the application. */ public String getGroupId() { return this.groupId; } /** * Get the artifact ID of the application. */ public String getArtifactId() { return this.artifactId; } /** * Fluent builder API for {@link Settings}. */ public static final class Builder { @Nullable private Path sourceOutput; @Nullable private Path resourceOutput; @Nullable private Path classOutput; @Nullable private String groupId; @Nullable private String artifactId; private Builder() { // internal constructor } /** * Set the output directory for generated sources. * @param sourceOutput the location of generated sources * @return this builder for method chaining */ public Builder sourceOutput(Path sourceOutput) { this.sourceOutput = sourceOutput; return this; } /** * Set the output directory for generated resources. * @param resourceOutput the location of generated resources * @return this builder for method chaining */ public Builder resourceOutput(Path resourceOutput) { this.resourceOutput = resourceOutput; return this; } /** * Set the output directory for generated classes. * @param classOutput the location of generated classes * @return this builder for method chaining */ public Builder classOutput(Path classOutput) { this.classOutput = classOutput; return this; } /** * Set the group ID of the application. * @param groupId the group ID of the application, used to locate * {@code native-image.properties} * @return this builder for method chaining */ public Builder groupId(String groupId) { this.groupId = groupId; return this; } /** * Set the artifact ID of the application. * @param artifactId the artifact ID of the application, used to locate * {@code native-image.properties} * @return this builder for method chaining */ public Builder artifactId(String artifactId) { this.artifactId = artifactId; return this; } /** * Build the {@link Settings} configured in this {@code Builder}. */ public Settings build() { Assert.notNull(this.sourceOutput, "'sourceOutput' must not be null"); Assert.notNull(this.resourceOutput, "'resourceOutput' must not be null"); Assert.notNull(this.classOutput, "'classOutput' must not be null"); Assert.hasText(this.groupId, "'groupId' must not be null or empty"); Assert.hasText(this.artifactId, "'artifactId' must not be null or empty"); return new Settings(this.sourceOutput, this.resourceOutput, this.classOutput, this.groupId, this.artifactId); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy