1 package lombok.maven;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.lang.reflect.InvocationTargetException;
6 import java.nio.charset.Charset;
7 import java.nio.charset.UnsupportedCharsetException;
8 import java.util.ArrayList;
9 import java.util.List;
10 import java.util.Map;
11
12 import org.apache.commons.lang3.JavaVersion;
13 import org.apache.commons.lang3.StringUtils;
14 import org.apache.commons.lang3.SystemUtils;
15 import org.apache.maven.artifact.Artifact;
16 import org.apache.maven.plugin.AbstractMojo;
17 import org.apache.maven.plugin.MojoExecutionException;
18 import org.apache.maven.plugin.logging.Log;
19 import org.apache.maven.plugin.descriptor.PluginDescriptor;
20 import org.apache.maven.plugins.annotations.Component;
21 import org.apache.maven.plugins.annotations.Parameter;
22 import org.apache.maven.project.MavenProject;
23 import org.sonatype.plexus.build.incremental.BuildContext;
24
25 import lombok.launch.Delombok;
26
27
28
29
30
31
32
33 public abstract class AbstractDelombokMojo extends AbstractMojo {
34
35
36
37
38 @Parameter(property="lombok.delombok.skip", defaultValue="false", required=true)
39 protected boolean skip;
40
41
42
43
44 @Parameter(property="lombok.encoding", defaultValue="${project.build.sourceEncoding}", required=true)
45 protected String encoding;
46
47
48
49
50 @Parameter(property="lombok.verbose", defaultValue="false", required=true)
51 protected boolean verbose;
52
53
54
55
56 @Parameter(property="lombok.addOutputDirectory", defaultValue="true", required=true)
57 protected boolean addOutputDirectory;
58
59
60
61
62 @Parameter
63 protected Map<String, String> formatPreferences;
64
65
66
67
68 @Parameter(property="project", required=true, readonly=true)
69 protected MavenProject project;
70
71
72
73
74 @Parameter(property="plugin.artifacts", required=true, readonly=true)
75 private List<Artifact> pluginArtifacts;
76
77 @Parameter(property="plugin", required=true, readonly=true)
78 protected PluginDescriptor pluginDescriptor;
79
80
81
82
83 @Component
84 private BuildContext buildContext;
85
86 protected abstract String getGoalDescription ();
87
88 protected abstract File getOutputDirectory();
89
90 protected abstract File getSourceDirectory();
91
92 protected abstract String getSourcePath();
93
94 protected abstract void addSourceRoot(String path);
95
96 @Override
97 public void execute() throws MojoExecutionException {
98 final Log logger = getLog();
99 assert null != logger;
100
101 final String goal = getGoalDescription();
102 logger.debug("Starting " + goal);
103 final File outputDirectory = getOutputDirectory();
104 logger.debug("outputDirectory: " + outputDirectory);
105 final File sourceDirectory = getSourceDirectory();
106 logger.debug("sourceDirectory: " + sourceDirectory);
107 final String sourcePath = getSourcePath();
108 logger.debug("sourcePath: " + sourcePath);
109
110 if (this.skip) {
111 logger.warn("Skipping " + goal);
112 } else if (sourceDirectory.exists()) {
113
114 final StringBuilder classPathBuilder = new StringBuilder();
115 for (final Object artifact : project.getArtifacts()) {
116 classPathBuilder.append(((Artifact)artifact).getFile()).append(File.pathSeparatorChar);
117 }
118 for (final Artifact artifact : pluginArtifacts) {
119 classPathBuilder.append(artifact.getFile()).append(File.pathSeparatorChar);
120 }
121
122 if (!SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_9)) {
123 final String javaHome = System.getProperty("java.home");
124 final File toolsJar = new File (javaHome,
125 ".." + File.separatorChar + "lib" + File.separatorChar + "tools.jar");
126 if (toolsJar.exists()) {
127 try {
128 pluginDescriptor.getClassRealm().addURL(toolsJar.toURI().toURL());
129 } catch (final IOException e) {
130 logger.warn("Unable to add tools.jar; " + toolsJar);
131 }
132 } else {
133 logger.warn("Unable to detect tools.jar; java.home is " + javaHome);
134 }
135 }
136 final String classPath = classPathBuilder.toString();
137 logger.debug("classpath: " + classPath);
138 try {
139 final DelombokDelombok delombok = new Delombok();
140 delombok.setVerbose(this.verbose);
141 delombok.setClasspath(classPath);
142
143 if (StringUtils.isNotBlank(this.encoding)) {
144 try {
145 delombok.setCharset(this.encoding);
146 } catch (final UnsupportedCharsetException e) {
147 logger.error("The encoding parameter is invalid; Please check!", e);
148 throw new MojoExecutionException("Unknown charset: " + this.encoding, e);
149 }
150 } else {
151 logger.warn("No encoding specified; using default: " + Charset.defaultCharset());
152 }
153
154 if (null != formatPreferences && !formatPreferences.isEmpty()) {
155 try {
156
157 final List<String> formatOptions = new ArrayList<String>(formatPreferences.size());
158 for (final Map.Entry<String, String> entry : formatPreferences.entrySet()) {
159 final String key = entry.getKey();
160
161 formatOptions.add( "pretty".equalsIgnoreCase(key) ? key : (key + ':' + entry.getValue()) );
162 }
163 delombok.setFormatPreferences(delombok.formatOptionsToMap(formatOptions));
164 } catch (final Exception e) {
165 logger.error("The formatPreferences parameter is invalid; Please check!", e);
166 throw new MojoExecutionException("Invalid formatPreferences: " + this.formatPreferences, e);
167 }
168 }
169
170 try {
171 delombok.setOutput(outputDirectory);
172 delombok.setSourcepath(getSourcePath());
173 delombok.addDirectory(sourceDirectory);
174 if (buildContext.hasDelta(sourceDirectory)) {
175 delombok.delombok();
176 logger.info(goal + " complete.");
177
178 if (this.addOutputDirectory) {
179
180 addSourceRoot(outputDirectory.getCanonicalPath());
181
182 buildContext.refresh(outputDirectory);
183 }
184 } else {
185 logger.info(goal + " skipped; No deltas detected.");
186 }
187 } catch (final IOException e) {
188 logger.error("Unable to delombok!", e);
189 throw new MojoExecutionException("I/O problem during delombok", e);
190 }
191 } catch (final ClassNotFoundException e) {
192 throw new MojoExecutionException("Unable to delombok", e);
193 } catch (final IllegalAccessException e) {
194 throw new MojoExecutionException("Unable to delombok", e);
195 } catch (final InvocationTargetException e) {
196 throw new MojoExecutionException("Unable to delombok", e);
197 } catch (final InstantiationException e) {
198 throw new MojoExecutionException("Unable to delombok", e);
199 } catch (final NoSuchMethodException e) {
200 throw new MojoExecutionException("Unable to delombok", e);
201 }
202 } else {
203 logger.warn("Skipping " + goal + "; no source to process.");
204 }
205 }
206 }