1 package org.andromda.maven.plugin.andromdapp;
2
3 import java.io.File;
4 import java.io.FileReader;
5 import java.net.URL;
6 import java.util.ArrayList;
7 import java.util.LinkedHashMap;
8 import java.util.List;
9 import java.util.Map;
10 import org.apache.commons.io.FileUtils;
11 import org.apache.maven.artifact.Artifact;
12 import org.apache.maven.artifact.factory.ArtifactFactory;
13 import org.apache.maven.model.Model;
14 import org.apache.maven.model.Parent;
15 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
16 import org.apache.maven.plugin.AbstractMojo;
17 import org.apache.maven.plugin.MojoExecutionException;
18 import org.apache.maven.plugin.MojoFailureException;
19 import org.apache.maven.project.MavenProject;
20 import org.codehaus.plexus.util.DirectoryScanner;
21
22
23
24
25
26
27
28
29
30
31 public class SymbolicLinkExplodedEarMojo
32 extends AbstractMojo
33 {
34
35
36
37
38
39
40
41 protected MavenProject project;
42
43
44
45
46
47
48 private String deployLocation;
49
50
51
52
53
54
55
56
57 private int rootProjectLimit;
58
59
60
61
62
63
64
65
66
67 private ArtifactFactory artifactFactory;
68
69
70
71
72 private static final String LN_WINDOWS = "junction.exe";
73
74
75
76
77 private static final String LN_UNIX = "ln -s";
78
79
80
81
82 private static boolean isWindows = false;
83
84 private static final String WINDOWS = "Windows";
85
86 static
87 {
88 final String osName = System.getProperty("os.name");
89 if (osName.contains(WINDOWS))
90 {
91 isWindows = true;
92 }
93 }
94
95
96
97
98 public void execute()
99 throws MojoExecutionException, MojoFailureException
100 {
101 try
102 {
103 final File earDirectory =
104 new File(this.project.getBuild().getDirectory() + '/' + project.getBuild().getFinalName());
105 final Map<String, Artifact> artifacts = new LinkedHashMap<String, Artifact>();
106 for (final Artifact artifact : this.getExplodedModuleArtifacts())
107 {
108 artifacts.put(
109 artifact.getFile().getName(),
110 artifact);
111 }
112 if (earDirectory.exists() && earDirectory.isDirectory())
113 {
114 String linkCommand;
115 if (isWindows)
116 {
117 linkCommand = LN_WINDOWS;
118 final File executableFile =
119 new File(System.getProperty("java.io.tmpdir") + '/' + System.getProperty("user.name"),
120 LN_WINDOWS);
121 if (!executableFile.exists())
122 {
123 final URL resource =
124 Thread.currentThread().getContextClassLoader().getResource(LN_WINDOWS);
125 FileUtils.copyURLToFile(
126 resource,
127 executableFile);
128 }
129 linkCommand = executableFile.toString();
130 }
131 else
132 {
133 linkCommand = LN_UNIX;
134 }
135 final File[] files = earDirectory.listFiles();
136 final File explodedEarDirectory = new File(earDirectory + "-exploded");
137 explodedEarDirectory.mkdirs();
138 for (int ctr = 0; ctr < files.length; ctr++)
139 {
140 final File file = files[ctr];
141 final String fileName = file.getName();
142 final Artifact artifact = artifacts.get(fileName);
143 if (artifact == null)
144 {
145 if (file.isFile())
146 {
147 FileUtils.copyFileToDirectory(
148 file,
149 explodedEarDirectory);
150 }
151 else
152 {
153 final File targetDirectory = new File(explodedEarDirectory,
154 file.getName());
155 targetDirectory.mkdir();
156 FileUtils.copyDirectory(
157 file,
158 targetDirectory);
159 }
160 }
161 else
162 {
163 final File targetFile = new File(explodedEarDirectory, fileName);
164 final File explodedArtifactDirectory =
165 new File(artifact.getFile().toString().replaceAll(
166 "\\." + artifact.getType(),
167 ""));
168 final String command;
169 if (!isWindows)
170 {
171 command = linkCommand + ' ' + explodedArtifactDirectory + ' ' +
172 targetFile.getAbsolutePath();
173 }
174 else
175 {
176 command = linkCommand + ' ' + targetFile.getAbsolutePath() + ' ' +
177 explodedArtifactDirectory;
178 }
179 if (this.getLog().isDebugEnabled())
180 {
181 this.getLog().debug("executing command: " + command);
182 }
183
184 if (targetFile.exists() && targetFile.isFile())
185 {
186 targetFile.delete();
187 }
188 if (targetFile.isDirectory())
189 {
190 this.getLog().info("NOT linking " + explodedArtifactDirectory + " to " + targetFile + " (already linked)");
191 }
192 else
193 {
194 this.getLog().info("linking " + explodedArtifactDirectory + " to " + targetFile);
195 Runtime.getRuntime().exec(command);
196 }
197 }
198 }
199
200 final File targetFile =
201 new File(this.deployLocation,
202 this.project.getBuild().getFinalName() + '.' + this.project.getPackaging());
203 final String command;
204 if (!isWindows)
205 {
206 command = linkCommand + ' ' + explodedEarDirectory + ' ' + targetFile.getAbsolutePath();
207 }
208 else
209 {
210 command = linkCommand + ' ' + targetFile.getAbsolutePath() + ' ' + explodedEarDirectory;
211 }
212 if (this.getLog().isDebugEnabled())
213 {
214 this.getLog().debug("executing command: " + command);
215 }
216 final File applicationContextXml = new File(explodedEarDirectory, "META-INF/application.xml");
217 FileUtils.touch(applicationContextXml);
218
219
220 if (targetFile.isFile())
221 {
222 targetFile.delete();
223 }
224 if (targetFile.isDirectory())
225 {
226 this.getLog().info("NOT linking " + explodedEarDirectory + " to " + targetFile + " (already linked)");
227 }
228 else
229 {
230 this.getLog().info("linking " + explodedEarDirectory + " to " + targetFile);
231 Runtime.getRuntime().exec(command);
232 }
233 }
234 }
235 catch (Exception exception)
236 {
237 throw new MojoExecutionException("A failure occurred while trying to link the ear", exception);
238 }
239 }
240
241
242
243
244 private MavenProject rootProject;
245
246
247
248
249
250
251
252
253 private MavenProject getRootProject()
254 throws MojoExecutionException
255 {
256 if (this.rootProject == null)
257 {
258 MavenProject root = null;
259 int ctr = 1;
260 for (root = this.project.getParent(); root.getParent() != null && ctr < this.rootProjectLimit; root = root.getParent(), ctr++)
261 {
262 }
263 this.rootProject = root;
264 }
265 return this.rootProject;
266 }
267
268 private static final String[] INCLUDE_ALL_POMS = new String[]{"*/**/pom.xml"};
269
270
271
272
273
274
275
276 private List<File> getPoms()
277 throws MojoExecutionException
278 {
279 final DirectoryScanner scanner = new DirectoryScanner();
280 scanner.setBasedir(this.getRootProject().getBasedir());
281 scanner.setIncludes(INCLUDE_ALL_POMS);
282 scanner.scan();
283 final List<File> poms = new ArrayList<File>();
284 for (int ctr = 0; ctr < scanner.getIncludedFiles().length; ctr++)
285 {
286 final File file = new File(
287 this.getRootProject().getBasedir(),
288 scanner.getIncludedFiles()[ctr]);
289 if (file.exists())
290 {
291 poms.add(file);
292 }
293 }
294 return poms;
295 }
296
297
298
299
300
301
302
303 private List<Artifact> getExplodedModuleArtifacts()
304 throws Exception
305 {
306 final List<Artifact> artifacts = new ArrayList<Artifact>();
307 final MavenXpp3Reader reader = new MavenXpp3Reader();
308
309 for (final File pom : this.getPoms())
310 {
311 FileReader freader = new FileReader(pom);
312 final Model model = reader.read(freader);
313 String groupId = model.getGroupId();
314 for (Parent parent = model.getParent(); groupId == null && model.getParent() != null;
315 parent = model.getParent())
316 {
317 groupId = parent.getGroupId();
318 }
319 String version = model.getVersion();
320 for (Parent parent = model.getParent(); version == null && model.getParent() != null;
321 parent = model.getParent())
322 {
323 version = parent.getVersion();
324 }
325 final Artifact artifact =
326 this.artifactFactory.createArtifact(
327 groupId,
328 model.getArtifactId(),
329 version,
330 null,
331 model.getPackaging());
332 final File pomParent = pom.getParentFile();
333 final String finalName = model.getArtifactId() + '-' + version;
334 final File explodedDirectory = new File(pomParent, "target/" + finalName);
335 final File artifactFile = new File(explodedDirectory + "." + model.getPackaging());
336 if (explodedDirectory.isDirectory() && artifactFile.exists() &&
337 !finalName.equals(this.project.getBuild().getFinalName()))
338 {
339 artifacts.add(artifact);
340 artifact.setFile(artifactFile);
341 }
342 try
343 {
344 freader.close();
345 }
346 catch (Exception ex)
347 {
348
349 }
350 }
351 return artifacts;
352 }
353 }