1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package io.wcm.devops.conga.plugins.aem.maven;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Set;
29
30 import javax.inject.Inject;
31
32 import org.apache.commons.lang3.StringUtils;
33 import org.apache.maven.plugin.MojoExecutionException;
34 import org.apache.maven.plugin.MojoFailureException;
35 import org.apache.maven.plugins.annotations.Mojo;
36 import org.apache.maven.plugins.annotations.Parameter;
37 import org.codehaus.plexus.archiver.ArchiverException;
38 import org.codehaus.plexus.archiver.zip.ZipArchiver;
39
40 import com.google.inject.name.Named;
41
42 import io.wcm.devops.conga.generator.util.FileUtil;
43 import io.wcm.devops.conga.plugins.aem.maven.model.ModelParser;
44
45
46
47
48
49
50 @Mojo(name = "cloudmanager-dispatcher-config", threadSafe = true)
51 public final class CloudManagerDispatcherConfigMojo extends AbstractCloudManagerMojo {
52
53 private static final String ROLE_AEM_DISPATCHER_CLOUD = "aem-dispatcher-cloud";
54
55
56
57
58 @Parameter(property = "conga.cloudManager.dispatcherConfig.skip", defaultValue = "false")
59 private boolean skip;
60
61 @Inject
62 @Named("zip")
63 private ZipArchiver zipArchiver;
64
65 @Parameter(defaultValue = "${project.build.outputTimestamp}")
66 private String outputTimestamp;
67
68 @Override
69 public void execute() throws MojoExecutionException, MojoFailureException {
70 if (skip) {
71 return;
72 }
73
74 int dispatcherNodeCount = 0;
75 List<File> environmentDirs = getEnvironmentDir();
76 for (File environmentDir : environmentDirs) {
77 List<File> nodeDirs = getNodeDirs(environmentDir);
78 for (File nodeDir : nodeDirs) {
79 ModelParser modelParser = new ModelParser(nodeDir);
80 if (modelParser.hasRole(ROLE_AEM_DISPATCHER_CLOUD)) {
81 buildDispatcherConfig(environmentDir, nodeDir);
82 dispatcherNodeCount++;
83 }
84 }
85 }
86
87 if (dispatcherNodeCount > 1) {
88 throw new MojoFailureException("More than one node with role '" + ROLE_AEM_DISPATCHER_CLOUD + "' found - "
89 + "AEM Cloud service supports only a single dispatcher configuration.");
90 }
91 }
92
93 private void buildDispatcherConfig(File environmentDir, File nodeDir) throws MojoExecutionException {
94 File targetFile = new File(getTargetDir(), environmentDir.getName() + "." + nodeDir.getName() + ".dispatcher-config.zip");
95
96 try {
97 String basePath = toZipDirectoryPath(nodeDir);
98 addZipDirectory(basePath, nodeDir, Collections.singleton(ModelParser.MODEL_FILE));
99 zipArchiver.setDestFile(targetFile);
100
101 BuildOutputTimestamp buildOutputTimestamp = new BuildOutputTimestamp(outputTimestamp);
102 if (buildOutputTimestamp.isValid()) {
103 zipArchiver.configureReproducibleBuild(buildOutputTimestamp.toFileTime());
104 }
105
106 zipArchiver.createArchive();
107 }
108 catch (ArchiverException | IOException ex) {
109 throw new MojoExecutionException("Unable to build file " + targetFile.getPath() + ": " + ex.getMessage(), ex);
110 }
111 }
112
113
114
115
116
117
118
119
120
121 @SuppressWarnings("java:S3776")
122 private void addZipDirectory(String basePath, File directory, Set<String> excludeFiles) throws IOException {
123 String directoryPath = toZipDirectoryPath(directory);
124 if (StringUtils.startsWith(directoryPath, basePath)) {
125 String relativeDirectoryPath = StringUtils.substring(directoryPath, basePath.length());
126 File[] files = directory.listFiles();
127 if (files != null) {
128 for (File file : files) {
129 if (excludeFiles.contains(file.getName())) {
130 continue;
131 }
132 if (file.isDirectory()) {
133 addZipDirectory(basePath, file, Collections.emptySet());
134 }
135 else if (Files.isSymbolicLink(file.toPath())) {
136 Path linkPath = file.toPath();
137 Path targetPath = linkPath.toRealPath();
138 Path symlinkPath = file.getParentFile().toPath().relativize(targetPath);
139 zipArchiver.addSymlink(relativeDirectoryPath + file.getName(), sanitizePathSeparators(symlinkPath.toString()));
140 }
141 else {
142 zipArchiver.addFile(file, relativeDirectoryPath + file.getName());
143 }
144 }
145 }
146 }
147 }
148
149 private String toZipDirectoryPath(File directory) {
150 String canoncialPath = FileUtil.getCanonicalPath(directory);
151 return sanitizePathSeparators(canoncialPath) + "/";
152 }
153
154 private String sanitizePathSeparators(String path) {
155 return StringUtils.replace(path, "\\", "/");
156 }
157
158 }