1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.ejb;
20
21 import javax.inject.Inject;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.List;
28
29 import org.apache.commons.io.input.XmlStreamReader;
30 import org.apache.maven.archiver.MavenArchiveConfiguration;
31 import org.apache.maven.archiver.MavenArchiver;
32 import org.apache.maven.artifact.DependencyResolutionRequiredException;
33 import org.apache.maven.execution.MavenSession;
34 import org.apache.maven.plugin.AbstractMojo;
35 import org.apache.maven.plugin.MojoExecutionException;
36 import org.apache.maven.plugins.annotations.LifecyclePhase;
37 import org.apache.maven.plugins.annotations.Mojo;
38 import org.apache.maven.plugins.annotations.Parameter;
39 import org.apache.maven.plugins.annotations.ResolutionScope;
40 import org.apache.maven.project.MavenProject;
41 import org.apache.maven.project.MavenProjectHelper;
42 import org.apache.maven.shared.filtering.FilterWrapper;
43 import org.apache.maven.shared.filtering.MavenFileFilter;
44 import org.apache.maven.shared.filtering.MavenFilteringException;
45 import org.apache.maven.shared.filtering.MavenResourcesExecution;
46 import org.codehaus.plexus.archiver.ArchiverException;
47 import org.codehaus.plexus.archiver.jar.JarArchiver;
48 import org.codehaus.plexus.archiver.jar.ManifestException;
49 import org.codehaus.plexus.util.FileUtils;
50
51
52
53
54
55
56
57 @Mojo(
58 name = "ejb",
59 requiresDependencyResolution = ResolutionScope.RUNTIME,
60 threadSafe = true,
61 defaultPhase = LifecyclePhase.PACKAGE)
62 public class EjbMojo extends AbstractMojo {
63 private static final List<String> DEFAULT_INCLUDES_LIST = Collections.unmodifiableList(Arrays.asList("**/**"));
64
65 private static final String EJB_TYPE = "ejb";
66
67 private static final String EJB_CLIENT_TYPE = "ejb-client";
68
69
70 private static final List<String> DEFAULT_CLIENT_EXCLUDES_LIST = Collections.unmodifiableList(
71 Arrays.asList("**/*Bean.class", "**/*CMP.class", "**/*Session.class", "**/package.html"));
72
73
74
75
76
77 public static final String DEFAULT_CLIENT_CLASSIFIER = "client";
78
79
80
81
82 public static final String DEFAULT_EJBJAR = "META-INF/ejb-jar.xml";
83
84
85
86
87 @Parameter(defaultValue = "${project.build.directory}", required = true, readonly = true)
88 private File outputDirectory;
89
90
91
92
93 @Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
94 private File sourceDirectory;
95
96
97
98
99 @Parameter(defaultValue = "${project.build.finalName}", readonly = true)
100 private String jarName;
101
102
103
104
105 @Parameter
106 private String classifier;
107
108
109
110
111
112
113 @Parameter(defaultValue = DEFAULT_CLIENT_CLASSIFIER)
114 private String clientClassifier;
115
116
117
118
119 @Parameter(defaultValue = DEFAULT_EJBJAR)
120 private String ejbJar;
121
122
123
124
125 @Parameter(defaultValue = "false")
126 private boolean generateClient;
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 @Parameter
144 private List<String> clientExcludes;
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160 @Parameter
161 private List<String> clientIncludes;
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 @Parameter
178 private List<String> excludes;
179
180
181
182
183 @Parameter(defaultValue = "${project}", readonly = true, required = true)
184 private MavenProject project;
185
186
187
188
189
190
191
192
193
194
195
196
197
198 @Parameter(defaultValue = "3.1")
199 private String ejbVersion;
200
201
202
203
204
205 @Parameter
206 private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
207
208
209
210
211
212
213 @Parameter(defaultValue = "false")
214 private boolean escapeBackslashesInFilePath;
215
216
217
218
219
220
221 @Parameter
222 protected String escapeString;
223
224
225
226
227
228
229 @Parameter(defaultValue = "false")
230 private boolean filterDeploymentDescriptor;
231
232
233
234
235
236
237 @Parameter
238 private List<String> filters;
239
240
241
242
243 @Parameter(defaultValue = "${session}", readonly = true, required = true)
244 private MavenSession session;
245
246
247
248
249
250
251
252
253 @Parameter(defaultValue = "${project.build.outputTimestamp}")
254 private String outputTimestamp;
255
256
257
258
259 private final JarArchiver jarArchiver = new JarArchiver();
260
261
262
263
264 private JarArchiver clientJarArchiver = new JarArchiver();
265
266
267
268
269 private final MavenProjectHelper projectHelper;
270
271
272
273
274 private final MavenFileFilter mavenFileFilter;
275
276 @Inject
277 public EjbMojo(MavenProjectHelper projectHelper, MavenFileFilter mavenFileFilter) {
278 this.projectHelper = projectHelper;
279 this.mavenFileFilter = mavenFileFilter;
280 }
281
282
283
284
285 public void execute() throws MojoExecutionException {
286
287 if (!sourceDirectory.exists()) {
288 getLog().warn("The created EJB jar will be empty cause the " + sourceDirectory.getPath()
289 + " did not exist.");
290 sourceDirectory.mkdirs();
291 }
292
293 File jarFile = generateEjb();
294
295 if (hasClassifier()) {
296 if (!isClassifierValid()) {
297 String message = "The given classifier '" + getClassifier() + "' is not valid.";
298 getLog().error(message);
299 throw new MojoExecutionException(message);
300 }
301
302
303
304 projectHelper.attachArtifact(project, EJB_TYPE, getClassifier(), jarFile);
305 } else {
306 if (projectHasAlreadySetAnArtifact()) {
307 throw new MojoExecutionException("You have to use a classifier "
308 + "to attach supplemental artifacts to the project instead of replacing them.");
309 }
310
311 project.getArtifact().setFile(jarFile);
312 }
313
314 if (generateClient) {
315 File clientJarFile = generateEjbClient();
316 if (hasClientClassifier()) {
317 if (!isClientClassifierValid()) {
318 String message = "The given client classifier '" + getClientClassifier() + "' is not valid.";
319 getLog().error(message);
320 throw new MojoExecutionException(message);
321 }
322
323 projectHelper.attachArtifact(project, EJB_CLIENT_TYPE, getClientClassifier(), clientJarFile);
324 } else {
325
326
327 projectHelper.attachArtifact(project, "ejb-client", getClientClassifier(), clientJarFile);
328 }
329 }
330 }
331
332 private boolean projectHasAlreadySetAnArtifact() {
333 if (getProject().getArtifact().getFile() != null) {
334 return getProject().getArtifact().getFile().isFile();
335 } else {
336 return false;
337 }
338 }
339
340 private File generateEjb() throws MojoExecutionException {
341 File jarFile = EjbHelper.getJarFile(outputDirectory, jarName, getClassifier());
342
343 getLog().info("Building EJB " + jarName + " with EJB version " + ejbVersion);
344
345 MavenArchiver archiver = new MavenArchiver();
346
347 archiver.setArchiver(jarArchiver);
348
349 archiver.setCreatedBy("Maven EJB Plugin", "org.apache.maven.plugins", "maven-ejb-plugin");
350
351 archiver.setOutputFile(jarFile);
352
353
354 archiver.configureReproducibleBuild(outputTimestamp);
355
356 File deploymentDescriptor = new File(sourceDirectory, ejbJar);
357
358 checkEJBVersionCompliance(deploymentDescriptor);
359
360 try {
361 List<String> defaultExcludes = Arrays.asList(ejbJar, "**/package.html");
362
363 IncludesExcludes ie =
364 new IncludesExcludes(Collections.emptyList(), excludes, DEFAULT_INCLUDES_LIST, defaultExcludes);
365
366 archiver.getArchiver().addDirectory(sourceDirectory, ie.resultingIncludes(), ie.resultingExcludes());
367
368
369 if (deploymentDescriptor.exists()) {
370
371 if (filterDeploymentDescriptor) {
372 filterDeploymentDescriptor(deploymentDescriptor);
373 }
374 archiver.getArchiver().addFile(deploymentDescriptor, ejbJar);
375 }
376
377
378 archiver.createArchive(session, project, archive);
379 } catch (ArchiverException | ManifestException | IOException | DependencyResolutionRequiredException e) {
380 throw new MojoExecutionException("There was a problem creating the EJB archive: " + e.getMessage(), e);
381 } catch (MavenFilteringException e) {
382 throw new MojoExecutionException(
383 "There was a problem filtering the deployment descriptor: " + e.getMessage(), e);
384 }
385
386 return jarFile;
387 }
388
389 private File generateEjbClient() throws MojoExecutionException {
390 File clientJarFile = EjbHelper.getJarFile(outputDirectory, jarName, getClientClassifier());
391
392 getLog().info("Building EJB client " + clientJarFile.getPath());
393
394 MavenArchiver clientArchiver = new MavenArchiver();
395
396 clientArchiver.setArchiver(clientJarArchiver);
397
398 clientArchiver.setCreatedBy("Maven EJB Plugin", "org.apache.maven.plugins", "maven-ejb-plugin");
399
400 clientArchiver.setOutputFile(clientJarFile);
401
402
403 clientArchiver.configureReproducibleBuild(outputTimestamp);
404
405 try {
406
407 IncludesExcludes ie = new IncludesExcludes(
408 clientIncludes, clientExcludes, DEFAULT_INCLUDES_LIST, DEFAULT_CLIENT_EXCLUDES_LIST);
409
410 clientArchiver.getArchiver().addDirectory(sourceDirectory, ie.resultingIncludes(), ie.resultingExcludes());
411
412 clientArchiver.createArchive(session, project, archive);
413
414 } catch (ArchiverException | ManifestException | IOException | DependencyResolutionRequiredException e) {
415 throw new MojoExecutionException(
416 "There was a problem creating the EJB client archive: " + e.getMessage(), e);
417 }
418
419 return clientJarFile;
420 }
421
422 static void validateEjbVersion(String ejbVersion) throws MojoExecutionException {
423 if (!ejbVersion.matches("\\A[2-4]\\.[0-9]\\z")) {
424 throw new MojoExecutionException(
425 "ejbVersion is not valid: " + ejbVersion + ". Must be 2.x, 3.x or 4.x (where x is a digit)");
426 }
427 }
428
429 private void checkEJBVersionCompliance(File deploymentDescriptor) throws MojoExecutionException {
430 validateEjbVersion(ejbVersion);
431
432 if (ejbVersion.matches("\\A2\\.[0-9]\\z") && !deploymentDescriptor.exists()) {
433 throw new MojoExecutionException("Error assembling EJB: " + ejbJar + " is required for ejbVersion 2.x");
434 }
435 }
436
437 private void filterDeploymentDescriptor(File deploymentDescriptor) throws MavenFilteringException, IOException {
438 getLog().debug("Filtering deployment descriptor.");
439 MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution();
440 mavenResourcesExecution.setEscapeString(escapeString);
441 List<FilterWrapper> filterWrappers = mavenFileFilter.getDefaultFilterWrappers(
442 project, filters, escapeBackslashesInFilePath, this.session, mavenResourcesExecution);
443
444
445 File unfilteredDeploymentDescriptor = new File(sourceDirectory, ejbJar + ".unfiltered");
446 FileUtils.copyFile(deploymentDescriptor, unfilteredDeploymentDescriptor);
447 mavenFileFilter.copyFile(
448 unfilteredDeploymentDescriptor,
449 deploymentDescriptor,
450 true,
451 filterWrappers,
452 getEncoding(unfilteredDeploymentDescriptor));
453
454 FileUtils.forceDelete(unfilteredDeploymentDescriptor);
455 }
456
457
458
459
460 private boolean hasClassifier() {
461 return EjbHelper.hasClassifier(getClassifier());
462 }
463
464
465
466
467
468 private boolean hasClientClassifier() {
469 return EjbHelper.hasClassifier(getClientClassifier());
470 }
471
472 private boolean isClassifierValid() {
473 return EjbHelper.isClassifierValid(getClassifier());
474 }
475
476 private boolean isClientClassifierValid() {
477 return EjbHelper.isClassifierValid(getClientClassifier());
478 }
479
480
481
482
483
484
485
486
487 private String getEncoding(File xmlFile) throws IOException {
488 try (XmlStreamReader xmlReader =
489 XmlStreamReader.builder().setFile(xmlFile).get()) {
490 return xmlReader.getEncoding();
491 }
492 }
493
494 public String getClassifier() {
495 return classifier;
496 }
497
498 public String getClientClassifier() {
499 return clientClassifier;
500 }
501
502 public MavenProject getProject() {
503 return project;
504 }
505 }