View Javadoc
1   /*
2    * Copyright 2017-2022 original authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package io.micronaut.build.aot;
17  
18  import io.micronaut.build.Packaging;
19  import io.micronaut.build.services.CompilerService;
20  import org.apache.commons.io.FileUtils;
21  import org.apache.maven.execution.MavenSession;
22  import org.apache.maven.plugin.AbstractMojo;
23  import org.apache.maven.plugin.MojoExecutionException;
24  import org.apache.maven.plugin.MojoFailureException;
25  import org.apache.maven.plugins.annotations.Parameter;
26  import org.apache.maven.project.MavenProject;
27  import org.eclipse.aether.RepositorySystem;
28  import org.eclipse.aether.resolution.DependencyResolutionException;
29  
30  import java.io.File;
31  import java.io.IOException;
32  
33  /**
34   * Abstract Mojo for Micronaut AOT.
35   */
36  public abstract class AbstractMicronautAotMojo extends AbstractMojo {
37  
38      protected final CompilerService compilerService;
39  
40      protected final MavenProject mavenProject;
41  
42      protected final MavenSession mavenSession;
43  
44      protected final RepositorySystem repositorySystem;
45  
46      /**
47       * Micronaut AOT runtime. Possible values: <code>jit</code>, <code>native</code>.
48       */
49      @Parameter(property = "micronaut.aot.runtime", required = true, defaultValue = "jit")
50      protected String runtime;
51  
52      /**
53       * Micronaut AOT version.
54       */
55      @Parameter(property = "micronaut.aot.version", required = true)
56      protected String micronautAotVersion;
57  
58      /**
59       * Whether to enable or disable Micronaut AOT.
60       */
61      @Parameter(property = "micronaut.aot.enabled", defaultValue = "false")
62      protected boolean enabled;
63  
64      /**
65       * Directory where compiled application classes are.
66       */
67      @Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
68      protected File outputDirectory;
69  
70      public AbstractMicronautAotMojo(CompilerService compilerService, MavenProject mavenProject, MavenSession mavenSession, RepositorySystem repositorySystem) {
71          this.compilerService = compilerService;
72          this.mavenProject = mavenProject;
73          this.mavenSession = mavenSession;
74          this.repositorySystem = repositorySystem;
75      }
76  
77      abstract void onSuccess(File outputDir) throws MojoExecutionException;
78  
79      protected final File getBaseOutputDirectory() {
80          File targetDirectory = new File(mavenProject.getBuild().getDirectory(), "aot");
81          return new File(targetDirectory, runtime);
82      }
83  
84      protected final File outputFile(String name) {
85          return new File(getBaseOutputDirectory(), name);
86      }
87  
88      @Override
89      public final void execute() throws MojoExecutionException, MojoFailureException {
90          if (!enabled) {
91              return;
92          }
93          validateRuntime();
94          getLog().info("Running Micronaut AOT " + micronautAotVersion + " " + getName());
95          try {
96              File baseOutputDirectory = getBaseOutputDirectory();
97              clean(baseOutputDirectory);
98              clean(outputDirectory);
99              doExecute();
100             onSuccess(baseOutputDirectory);
101         } catch (DependencyResolutionException | IOException e) {
102             throw new MojoExecutionException("Unable to generate AOT optimizations", e);
103         }
104     }
105 
106     private void clean(File baseOutputDirectory) throws IOException {
107         if (baseOutputDirectory.exists()) {
108             getLog().debug("Deleting " + baseOutputDirectory.getAbsolutePath());
109             FileUtils.deleteDirectory(baseOutputDirectory);
110         }
111         baseOutputDirectory.mkdirs();
112     }
113 
114     private void validateRuntime() {
115         Packaging packaging = Packaging.of(mavenProject.getPackaging());
116         AotRuntime aotRuntime = AotRuntime.valueOf(runtime.toUpperCase());
117         switch (packaging) {
118             case JAR:
119             case DOCKER_CRAC:
120             case DOCKER:
121                 if (aotRuntime != AotRuntime.JIT) {
122                     warnRuntimeMismatchAndSetCorrectValue(AotRuntime.JIT);
123                 }
124                 break;
125 
126             case NATIVE_IMAGE:
127             case DOCKER_NATIVE:
128                 if (aotRuntime != AotRuntime.NATIVE) {
129                     warnRuntimeMismatchAndSetCorrectValue(AotRuntime.NATIVE);
130                 }
131                 break;
132             default:
133                 throw new IllegalArgumentException("Unsupported packaging: " + packaging);
134         }
135     }
136 
137     private void warnRuntimeMismatchAndSetCorrectValue(final AotRuntime correctRuntime) {
138         String correctRuntimeString = correctRuntime.name().toLowerCase();
139         getLog().warn("Packaging is set to [" + mavenProject.getPackaging() + "], but Micronaut AOT runtime is set to [" + runtime + "]. Setting AOT runtime to: [" + correctRuntimeString + "]");
140         this.runtime = correctRuntimeString;
141     }
142 
143     protected abstract void doExecute() throws DependencyResolutionException, MojoExecutionException;
144 
145     abstract String getName();
146 }