View Javadoc
1   package net.sf.environments;
2   
3   import java.io.File;
4   import java.io.FileFilter;
5   import java.io.IOException;
6   import java.util.ArrayList;
7   import java.util.Arrays;
8   import java.util.Collections;
9   import java.util.LinkedHashSet;
10  import java.util.List;
11  import java.util.logging.Level;
12  import java.util.logging.Logger;
13  import static net.sf.environments.EnvironmentArchiveConfiguration.MANIFEST_ENVIRONMENT_KEY;
14  
15  import org.apache.maven.archiver.MavenArchiveConfiguration;
16  import org.apache.maven.archiver.MavenArchiver;
17  import org.apache.maven.artifact.Artifact;
18  import org.apache.maven.artifact.DependencyResolutionRequiredException;
19  import org.apache.maven.execution.MavenSession;
20  import org.apache.maven.model.Resource;
21  import org.apache.maven.plugin.AbstractMojo;
22  import org.apache.maven.plugin.MojoExecutionException;
23  import org.apache.maven.plugin.MojoFailureException;
24  import org.apache.maven.plugins.annotations.Component;
25  import org.apache.maven.plugins.annotations.Parameter;
26  import org.apache.maven.project.MavenProject;
27  import org.apache.maven.project.MavenProjectHelper;
28  import org.apache.maven.shared.filtering.MavenFilteringException;
29  import org.apache.maven.shared.filtering.MavenResourcesExecution;
30  import org.apache.maven.shared.filtering.MavenResourcesFiltering;
31  import org.codehaus.plexus.archiver.ArchiverException;
32  import org.codehaus.plexus.archiver.jar.JarArchiver;
33  import org.codehaus.plexus.archiver.jar.ManifestException;
34  import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
35  import org.codehaus.plexus.archiver.util.DefaultFileSet;
36  import org.codehaus.plexus.util.FileUtils;
37  import org.codehaus.plexus.util.StringUtils;
38  
39  /**
40   * @author Karl-Heinz Marbaise
41   * <a href="mailto:khmarbaise@soebes.de">khmarbaise@soebes.de</a>
42   */
43  public abstract class AbstractEnvironmentsMojo
44  		extends AbstractMojo {
45  
46  	private static final String TARGET_PATHS_COMMAND_LINE_KEY = "mem.env-target-path";
47  	private static final String INDIVIDUAL_ENVIRONMENT_COMMAND_LINE_KEY = "em.env";
48  	
49  	/**
50  	 * The project currently being build.
51  	 */
52  	@Parameter(defaultValue = "${project}", required = true, readonly = true)
53  	private MavenProject mavenProject;
54  
55  	/**
56  	 * The current Maven session.
57  	 */
58  	@Parameter(defaultValue = "${session}", required = true, readonly = true)
59  	private MavenSession mavenSession;
60  
61  	/**
62  	 * The directory for the generated configuration packages.
63  	 */
64  	@Parameter(defaultValue = "${project.build.directory}", required = true, readonly = true)
65  	private File outputDirectory;
66  
67  	/**
68  	 * directory which contains the different environments
69  	 */
70  	// TODO: src/main ? property?
71  	@Parameter(defaultValue = "${basedir}/src/main/environments")
72  	private File sourceDirectory;
73  
74  	/**
75  	 * The character encoding scheme to be applied when filtering resources.
76  	 */
77  	@Parameter(defaultValue = "${project.build.sourceEncoding}")
78  	private String encoding;
79  
80  	/**
81  	 * Name of the generated JAR.
82  	 */
83  	@Parameter(defaultValue = "${project.build.finalName}", readonly = true)
84  	private String finalName;
85  
86  	@Component
87  	private MavenProjectHelper projectHelper;
88  
89  	/**
90  	 * The archive configuration to use. See
91  	 * <a href="http://maven.apache.org/shared/maven-archiver/index.html">Maven
92  	 * Archiver Reference</a>.
93  	 */	
94  	@Parameter
95  	private List<EnvironmentArchiveConfiguration> archives;
96  
97  	/**
98  	 * Expression preceded with the String won't be interpolated \${foo} will be
99  	 * replaced with ${foo}
100 	 */
101 	@Parameter
102 	private String escapeString;
103 
104 	/**
105 	 * Whether to escape backslashes and colons in windows-style paths.
106 	 */
107 	@Parameter(defaultValue = "true")
108 	private boolean escapeWindowsPaths;
109 
110 	/**
111 	 * Filter files.
112 	 *
113 	 * List of files which will be used to filter files in the directory defined
114 	 * in commonDir tag of the plugin configuration.
115 	 */
116 	@Parameter
117 	private List<String> filters;
118 
119 	/**
120 	 * Support filtering of filenames directories etc.
121 	 */
122 	@Parameter(defaultValue = "false")
123 	private boolean fileNameFiltering;
124 
125 	/**
126 	 * <p>
127 	 * Set of delimiters for expressions to filter within the resources. These
128 	 * delimiters are specified in the form 'beginToken*endToken'. If no '*' is
129 	 * given, the delimiter is assumed to be the same for start and end.
130 	 * </p>
131 	 * <p>
132 	 * So, the default filtering delimiters might be specified as:
133 	 * </p>
134 	 *
135 	 * <pre>
136 	 * &lt;delimiters&gt;
137 	 *   &lt;delimiter&gt;${*}&lt;/delimiter&gt;
138 	 *   &lt;delimiter&gt;@&lt;/delimiter&gt;
139 	 * &lt;/delimiters&gt;
140 	 * </pre>
141 	 * <p>
142 	 * Since the '@' delimiter is the same on both ends, we don't need to
143 	 * specify '@*@' (though we can).
144 	 * </p>
145 	 */
146 	@Parameter
147 	private LinkedHashSet<String> delimiters;
148 
149 	/**
150 	 * Use default delimiters in addition to custom delimiters, if any.
151 	 */
152 	@Parameter(defaultValue = "true")
153 	private boolean useDefaultDelimiters;
154 
155 	/**
156 	 * Include empty directories or not.
157 	 */
158 	@Parameter(defaultValue = "true")
159 	private boolean includeEmptyDirs;
160 
161 	/**
162 	 * Additional file extensions to not apply filtering (already defined are :
163 	 * jpg, jpeg, gif, bmp, png)
164 	 */
165 	@Parameter
166 	private List<String> nonFilteredFileExtensions;
167 
168 	/**
169 	 * Comma separated list of names of environments.
170 	 */
171 	@Parameter(defaultValue = "", name = "excludeEnvironments", required = false)
172 	protected String excludeEnvironments;
173 
174 	/**
175 	 * stop searching endToken at the end of line
176 	 */
177 	@Parameter(defaultValue = "false")
178 	private boolean supportMultiLineFiltering;
179 
180 	/**
181 	 * Name of the directory where files common to all environments are stored.
182 	 * Any and all files listed in this directory are included in all
183 	 * environment wars.
184 	 *
185 	 * The files are filtered using the filter files defined in filters tag of
186 	 * the plugin configuration.
187 	 *
188 	 * If commonDir isn't configured then it is assumed that there is no common
189 	 * directory. i.e. there is no default value for commonDir.
190 	 *
191 	 */
192 	@Parameter
193 	private String commonDir;
194 
195 	/**
196 	 * Set describe the resource target path. The path is relative to the
197 	 * target/classes directory (i.e.
198 	 * <code>${project.build.outputDirectory}</code>). For example, if you want
199 	 * that resource to appear in a specific package
200 	 * (<code>org.apache.maven.messages</code>), you must specify this element
201 	 * with this value: <code>org/apache/maven/messages</code>. This is not
202 	 * required if you simply put the resources in that directory structure at
203 	 * the source, however.
204 	 *
205 	 * @param targetPath
206 	 */
207 	@Parameter
208 	private String targetPath;
209 
210 	/**
211 	 * 
212 	 */	
213 	@Parameter
214 	private List<String> dirs;
215         
216 	@Component(role = MavenResourcesFiltering.class, hint = "default")
217 	protected MavenResourcesFiltering mavenResourcesFiltering;
218 	
219 	/**
220 	 * A booleans which help in avoiding the repetition of logging warning and error messages for common director feature.
221 	 */
222 	private boolean showCommonDirWarningMsg = true;
223 	private boolean showCommonDirErrorMsg = true;
224 	
225 	public List<EnvironmentArchiveConfiguration> getArchives() {
226 		return archives;
227 	}
228 	
229 	public MavenArchiveConfiguration getArchive(final String environment) {
230 		if (StringUtils.isBlank(environment) || getArchives() == null) {
231 			return new MavenArchiveConfiguration();
232 		}
233 		
234 		for (final EnvironmentArchiveConfiguration  archiveWrapper: getArchives()) {
235 			if (StringUtils.isNotBlank(archiveWrapper.getEnvironment()) 
236 					&& environment.trim().equals(archiveWrapper.getEnvironment())) {
237 				return archiveWrapper.getArchive();
238 			}
239 		}
240 		
241 		return new MavenArchiveConfiguration();
242 	}
243 	
244 	protected MavenArchiveConfiguration addEnvironmentToManifest(final MavenArchiveConfiguration archive, final String environment) {
245 		if (archive == null) return archive;
246 		String env = environment;
247 		if (StringUtils.isBlank(env)) env = "";
248 		
249 		if (!archive.getManifestEntries().containsKey(MANIFEST_ENVIRONMENT_KEY)) {
250 			archive.addManifestEntry(MANIFEST_ENVIRONMENT_KEY, env);
251 		}
252 		
253 		return archive;
254 	}
255 
256 	public MavenProject getMavenProject() {
257 		return mavenProject;
258 	}
259 
260 	public MavenSession getMavenSession() {
261 		return mavenSession;
262 	}
263 
264 	public File getOutputDirectory() {
265 		return outputDirectory;
266 	}
267 
268 	public MavenProjectHelper getProjectHelper() {
269 		return projectHelper;
270 	}
271 
272 	public File getSourceDirectory() {
273 		return sourceDirectory;
274 	}
275 
276 	public String getFinalName() {
277 		return finalName;
278 	}
279 
280 	public String getEncoding() {
281 		return encoding;
282 	}
283 
284 	/**
285 	 * @param resourceResult The directory where to search for different
286 	 * environments.
287 	 * @return The list of identified environments. This list is converted to
288 	 * lower case.
289 	 */
290 	protected String[] getTheEnvironments(File resourceResult) {
291 		File[] theResultingFolders = resourceResult.listFiles(new FileFilter() {
292 			@Override
293 			public boolean accept(File pathname) {
294 				return pathname.isDirectory() && pathname.exists();
295 			}
296 		});
297 
298 		String[] result = new String[theResultingFolders.length];
299 		for (int i = 0; i < theResultingFolders.length; i++) {
300 			getLog().debug("Folders: " + theResultingFolders[i].getName());
301 			result[i] = theResultingFolders[i].getName().toLowerCase();
302 		}
303 		return result;
304 	}
305 
306 	/**
307 	 * This will check if an environment (directory) contains a space cause the
308 	 * environment will later being used as a classifier which does not allow a
309 	 * space.
310 	 *
311 	 * @param environmens The environments which should be checked.
312 	 * @return The list contains the invalid environments. If the list is
313 	 * {@code empty} all environments are ok.
314 	 */
315 	protected List<String> environmentNamesAreValid(String[] environmens) {
316 		List<String> result = new ArrayList<>();
317 		for (String item : environmens) {
318 			if (item.contains(" ")) {
319 				result.add(item);
320 			}
321 		}
322 		return result;
323 	}
324 
325 	/**
326 	 * Returns the archive file to generate, based on an optional classifier.
327 	 *
328 	 * @param basedir the output directory
329 	 * @param finalName the name of the ear file
330 	 * @param classifier an optional classifier
331 	 * @param archiveExt Archive Extension
332 	 * @return the file to generate
333 	 */
334 	protected File getArchiveFile(File basedir, String finalName, String classifier, String archiveExt) {
335 		if (basedir == null) {
336 			throw new IllegalArgumentException("basedir is not allowed to be null");
337 		}
338 		if (finalName == null) {
339 			throw new IllegalArgumentException("finalName is not allowed to be null");
340 		}
341 		if (archiveExt == null) {
342 			throw new IllegalArgumentException("archiveExt is not allowed to be null");
343 		}
344 
345 		if (finalName.isEmpty()) {
346 			throw new IllegalArgumentException("finalName is not allowed to be empty.");
347 		}
348 		if (archiveExt.isEmpty()) {
349 			throw new IllegalArgumentException("archiveExt is not allowed to be empty.");
350 		}
351 
352 		StringBuilder fileName = new StringBuilder(finalName);
353 
354 		if (hasClassifier(classifier)) {
355 			fileName.append("-").append(classifier);
356 		}
357 
358 		fileName.append('.');
359 		fileName.append(archiveExt);
360 
361 		return new File(basedir, fileName.toString());
362 	}
363 
364 	public String getEscapeString() {
365 		return escapeString;
366 	}
367 
368 	public boolean isEscapeWindowsPaths() {
369 		return escapeWindowsPaths;
370 	}
371 
372 	public List<String> getFilters() {
373 		return filters;
374 	}
375 
376 	public boolean isFileNameFiltering() {
377 		return fileNameFiltering;
378 	}
379 
380 	public LinkedHashSet<String> getDelimiters() {
381 		return delimiters;
382 	}
383 
384 	public boolean isUseDefaultDelimiters() {
385 		return useDefaultDelimiters;
386 	}
387 
388 	public List<String> getNonFilteredFileExtensions() {
389 		return nonFilteredFileExtensions;
390 	}
391 
392 	public boolean isSupportMultiLineFiltering() {
393 		return supportMultiLineFiltering;
394 	}
395 
396 	public String getExcludeEnvironments() {
397 		return excludeEnvironments;
398 	}
399 
400 	public void setExcludeEnvironments(String excludeEnvironments) {
401 		this.excludeEnvironments = excludeEnvironments;
402 	}
403 
404 	private boolean hasClassifier(String classifier) {
405 		boolean result = false;
406 		if (classifier != null && classifier.trim().length() > 0) {
407 			result = true;
408 		}
409 
410 		return result;
411 	}
412 
413 	protected void deleteDirectoryOfPreviousRunIfExist(File directoryOfPreviousRun)
414 			throws MojoExecutionException {
415 
416 		if (directoryOfPreviousRun.exists()) {
417 			try {
418 				FileUtils.deleteDirectory(directoryOfPreviousRun);
419 			} catch (IOException e) {
420 				throw new MojoExecutionException("Failure while deleting " + directoryOfPreviousRun.getAbsolutePath(),
421 						e);
422 			}
423 		}
424 	}
425 
426 	/**
427 	 * Create the unpack directory for later unpacking of the main artifact.
428 	 *
429 	 * @return The directory which has been created.
430 	 * @throws org.apache.maven.plugin.MojoFailureException in case of failures.
431 	 * @throws MojoExecutionException in case of failures.
432 	 */
433 	protected File createUnpackDirectory() throws MojoFailureException, MojoExecutionException {
434 		// TODO: Should we use a different name or temp file? File.createTempFile( prefix, suffix );
435 		File unpackDirectory = new File(getOutputDirectory(), "multienv-maven-plugin-unpack");
436 
437 		deleteDirectoryOfPreviousRunIfExist(unpackDirectory);
438 
439 		if (!unpackDirectory.mkdirs()) {
440 			throw new MojoExecutionException("The unpack directory " + unpackDirectory.getAbsolutePath()
441 					+ " couldn't generated!");
442 		}
443 		return unpackDirectory;
444 	}
445 
446 	protected String getArchiveExtensionOfTheProjectMainArtifact()
447 			throws MojoExecutionException {
448 		if (getMavenProject().getArtifact() == null) {
449 			throw new MojoExecutionException("No main artifact has been set yet.");
450 		}
451 
452 		if (getMavenProject().getArtifact().getFile() == null) {
453 			throw new MojoExecutionException("No main artifact file has been set yet.");
454 		}
455 
456 		return FileUtils.getExtension(getMavenProject().getArtifact().getFile().getAbsolutePath()).toLowerCase();
457 
458 	}
459 
460 	protected String getArchiveExtensionOfTheArtifact(Artifact artifact)
461 			throws MojoExecutionException {
462 		if (artifact == null) {
463 			throw new MojoExecutionException("No artifact has been set yet.");
464 		}
465 
466 		if (artifact.getFile() == null) {
467 			throw new MojoExecutionException("No artifact file has been set yet.");
468 		}
469 
470 		return FileUtils.getExtension(artifact.getFile().getAbsolutePath()).toLowerCase();
471 
472 	}
473 
474 	protected File createPluginResourceOutput()
475 			throws MojoExecutionException {
476 		// TODO: Should we use a different name? Or temp File?
477 		File resourceResult = new File(getOutputDirectory(), "multienv-maven-plugin-resource-output");
478 
479 		deleteDirectoryOfPreviousRunIfExist(resourceResult);
480 
481 		if (!resourceResult.mkdirs()) {
482 			throw new MojoExecutionException("Failure while trying to create " + resourceResult.getAbsolutePath());
483 		}
484 
485 		return resourceResult;
486 	}
487 
488 	public boolean isIncludeEmptyDirs() {
489 		return includeEmptyDirs;
490 	}
491 
492 	public void setIncludeEmptyDirs(boolean includeEmptyDirs) {
493 		this.includeEmptyDirs = includeEmptyDirs;
494 	}
495 
496 	/**
497 	 * @param outputDir Output Directory where the resources need to be copied.
498 	 * @param environment absolute path of the environment directory.
499 	 * @param singleEnvironment boolean that specifies the user specified em.env command line switch.
500 	 * @throws org.apache.maven.plugin.MojoExecutionException in case of failures.
501 	 */
502 	protected void filterResources(File outputDir, final String environment, boolean singleEnvironment, final boolean ignoreTargetPath)
503 			throws MojoExecutionException {
504 		List<Resource> resources = new ArrayList<>();
505 		Resource res = new Resource();
506 		// TODO: Check how to prevent hard coding here?
507 		String baseEnvironmentResourcePath = StringUtils.join(new String[]{getSourceDirectory().getAbsolutePath(), environment}, "/");
508 		res.setDirectory(baseEnvironmentResourcePath);
509 		res.setFiltering(true);
510 		// TODO: Check if it makes sense to make this list configurable?
511 		res.setIncludes(Collections.singletonList("**/*"));
512 
513                 if (!ignoreTargetPath) {
514                     res.setTargetPath(getTargetPath(singleEnvironment, environment));
515                 }
516 
517 		resources.add(res);
518 
519 		List<String> filtersFile = new ArrayList<>();
520 
521 		addCommonDirResource(environment, filtersFile, resources, singleEnvironment, outputDir, ignoreTargetPath);
522 
523 		MavenResourcesExecution execution
524 				= new MavenResourcesExecution(resources, outputDir, getMavenProject(),
525 						getEncoding(), filtersFile, getNonFilteredFileExtensions(),
526 						getMavenSession());
527 
528 		execution.setEscapeString(getEscapeString());
529 		execution.setSupportMultiLineFiltering(isSupportMultiLineFiltering());
530 		execution.setIncludeEmptyDirs(isIncludeEmptyDirs());
531 		execution.setEscapeWindowsPaths(isEscapeWindowsPaths());
532 		execution.setFilterFilenames(isFileNameFiltering());
533 
534 		//// execution.setFilters( filters );
535 		//
536 		// // TODO: Check if we need a parameter?
537 		execution.setOverwrite(true);
538 		execution.setDelimiters(getDelimiters(), isUseDefaultDelimiters());
539 		execution.setEncoding(getEncoding());
540 		//
541 		// execution.setUseDefaultFilterWrappers( true );
542 
543 		if (getNonFilteredFileExtensions() != null) {
544 			execution.setNonFilteredFileExtensions(getNonFilteredFileExtensions());
545 		}
546 
547 		try {
548 			mavenResourcesFiltering.filterResources(execution);
549 		} catch (MavenFilteringException e) {
550 			getLog().error("Failure during filtering.", e);
551 			throw new MojoExecutionException("Failure during filtering", e);
552 		}
553 
554 	}
555 	
556 	protected void filterResourcesToTarget(String[] identifiedEnvironments) throws MojoExecutionException {
557 		File classes = new File(getOutputDirectory(), "classes");
558                 filterResourcesToDirectory(identifiedEnvironments, classes, true);
559 	}
560         
561         protected void filterResourcesToAdditionalDirectories(String[] identifiedEnvironments) throws MojoExecutionException {
562             if (dirs != null && !dirs.isEmpty()) {
563                 for (final String dir: dirs) {
564                     File d = new File(StringUtils.join(new String[]{mavenProject.getFile().getParentFile().getAbsolutePath(), dir }, "/"));
565                     if (!d.exists()) {
566                         d.mkdirs();
567                     }
568                     filterResourcesToDirectory(identifiedEnvironments, d, true);
569                 }
570             }
571         }
572         
573         private void filterResourcesToDirectory(final String[] identifiedEnvironments, final File dir, final boolean ignoreTargetPath) throws MojoExecutionException {
574             String memEnv = getMavenSession().getUserProperties().getProperty("em.env", null);
575 
576             if (StringUtils.isNotBlank(memEnv)) {
577                     if (Arrays.asList(identifiedEnvironments).contains(memEnv)) {
578                             filterResources(dir, memEnv, true, ignoreTargetPath);
579                     } else {
580                             getLog().error(String.format("Environment '%s' doesn't exist", memEnv));
581                     }
582             }
583         }
584         
585         protected String getTargetPath(final boolean singleEnvironment, final String environment) {
586             String tp = "";
587             if (singleEnvironment) {
588                 if (StringUtils.isNotBlank(targetPath)) {
589                     tp = targetPath;
590                 }
591             } else {
592                 if (StringUtils.isNotBlank(targetPath)) {
593                     tp = StringUtils.join(new String[]{environment, targetPath}, "/");
594                 } else {
595                     tp = environment;
596                 }
597             }
598             
599             return tp;
600         }
601 
602 	private void addCommonDirResource(final String environment, final List<String> filtersFile, final List<Resource> resources, 
603                 final boolean singleEnvironment, final File outputDir, final boolean ignoreTargetPath) {
604 		if (StringUtils.isNotBlank(environment)) {
605 			if (getFilters() != null && StringUtils.isNotBlank(commonDir)) {
606 				Resource common = new Resource();
607 
608 				common.setDirectory(StringUtils.join(new String[]{getSourceDirectory().getAbsolutePath(), getCommonDir()}, "/"));
609 				
610                                 if (!ignoreTargetPath) {
611                                     common.setTargetPath(getTargetPath(singleEnvironment, environment));
612                                 }
613 
614 				common.setFiltering(true);
615 				common.setIncludes(Collections.singletonList("**/*"));
616 				resources.add(common);
617 
618 				List<String> filtersRelativePaths = getFilters();
619 
620 				for (final String fileRelativePath : filtersRelativePaths) {
621 					String path = StringUtils.join(new String[]{getSourceDirectory().getPath(), environment, fileRelativePath}, "/");
622 					filtersFile.add(path);
623 				}
624 			} else if ((getFilters() == null || getFilters().isEmpty()) && StringUtils.isNotBlank(commonDir) && showCommonDirWarningMsg) {
625 				getLog().warn("A common directory is configured but no Filters are configured on MultiEnv maven plugin. Files in common directory will not be filtered but will be included in archives.");
626 				showCommonDirWarningMsg = false;
627 			} else if ((getFilters() != null && !getFilters().isEmpty()) && StringUtils.isBlank(commonDir) && showCommonDirErrorMsg) {
628 				getLog().error("Found filter configuration but no common directory configuration on MultiEnv maven plugin. MultiEnv maven filters configuration will have no effect.");
629 				showCommonDirErrorMsg = false;
630 			}
631 		}
632 	}
633     
634 	/**
635 	 * Returns true if this directory in src/main/environments doesn't represent
636 	 * an environment.
637 	 *
638 	 * The following directories are excluded - Comma separated list of
639 	 * directory names enclosed within excludeEnvironments tags in plugin
640 	 * configuration. - Directory name enclosed in common tag in plugin
641 	 * configuration.
642 	 *
643 	 * @param environment name of the environment.
644 	 * @return boolean indicating whether the specified environment should be skipped.
645 	 */
646 	protected boolean shouldSkip(final String environment) {
647 		boolean skip = false;
648 
649 		List<String> excludedEnvs = new ArrayList<>();
650 		if (StringUtils.isNotBlank(excludeEnvironments)) {
651 			for (final String excludedEnv : excludeEnvironments.split(",")) {
652 				if (StringUtils.isNotBlank(excludedEnv.trim())) {
653 					excludedEnvs.add(excludedEnv.trim());
654 				}
655 			}
656 		}
657 
658 		if (excludedEnvs.contains(environment)) {
659 			getLog().info(" - Excluding Environment: '" + environment + "'");
660 			skip = true;
661 		} else if (StringUtils.isNotBlank(getCommonDir()) && getCommonDir().equals(environment)) {
662 			getLog().info(" - Excluding common directory: '" + environment + "'");
663 			skip = true;
664 		} else {
665 			getLog().info("Building Environment: '" + environment + "'");
666 		}
667 
668 		return skip;
669 	}
670 
671 	protected void createLoggingOutput(String[] identifiedEnvironments) {
672 		getLog().info("");
673 		getLog().info("We have found " + identifiedEnvironments.length + " environments.");
674 
675 		StringBuilder sb = new StringBuilder();
676 		for (String identifiedEnvironment : identifiedEnvironments) {
677 			if (sb.length() > 0) {
678 				sb.append(',');
679 			}
680 			sb.append(identifiedEnvironment);
681 		}
682 
683 		getLog().info("We have the following environments: " + sb.toString());
684 		getLog().info("");
685 	}
686 
687 	/**
688 	 * This will validate the environments and will fail the build in case of
689 	 * errors.
690 	 *
691 	 * @param identifiedEnvironments The environments which will be checked.
692 	 * @throws MojoFailureException in case of invalid environments.
693 	 */
694 	protected void validateEnvironments(String[] identifiedEnvironments)
695 			throws MojoFailureException {
696 		List<String> environmentNamesAreValid = environmentNamesAreValid(identifiedEnvironments);
697 		if (!environmentNamesAreValid.isEmpty()) {
698 			for (String invalidEnv : environmentNamesAreValid) {
699 				getLog().error("Your environment '" + invalidEnv + "' name contains spaces which is not allowed.");
700 
701 			}
702 			throw new MojoFailureException("Your environment names contain spaces which are not allowed."
703 					+ "See previous error messages for details.");
704 		}
705 	}
706 
707 
708 	protected File createArchiveFile(File unpackDirectory, File targetDirectory, String directory, String archiveExt)
709 			throws NoSuchArchiverException, IOException, MojoExecutionException {
710 		final MavenArchiver mavenArchiver = new MavenArchiver();
711 
712 		mavenArchiver.setArchiver(getJarArchiver());
713 
714 		getJarArchiver().addFileSet(new DefaultFileSet(targetDirectory));
715 		
716 		if (unpackDirectory != null) {
717 			getJarArchiver().addFileSet(new DefaultFileSet(unpackDirectory));
718 		}
719 		// jarArchiver.setDuplicateBehavior( duplicate );
720 
721 		File resultArchive = getArchiveFile(getOutputDirectory(), getFinalName(), directory, archiveExt);
722 
723 		mavenArchiver.setOutputFile(resultArchive);
724 		try {
725 			MavenArchiveConfiguration archive = getArchive(directory);
726 			mavenArchiver.createArchive(getMavenSession(), getMavenProject(), addEnvironmentToManifest(archive, directory));
727 			getJarArchiver().reset();													// Reset JarArchiver, otherwise the manifest entries get reused across passes.
728 		} catch (ArchiverException | ManifestException | DependencyResolutionRequiredException e) {
729 			getLog().error(e.getMessage(), e);
730 			throw new MojoExecutionException(e.getMessage(), e);
731 		}
732 
733 		return resultArchive;
734 
735 	}
736 	
737 	protected String getCommonDir() {
738 		return commonDir;
739 	}
740 
741 	public String getTargetPath() {
742 		return targetPath;
743 	}
744 
745 	abstract protected JarArchiver getJarArchiver();
746 
747 }