1 package org.apache.maven.plugin.cxx;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import org.apache.commons.io.IOUtils;
22 import org.codehaus.plexus.util.StringUtils;
23 import org.apache.commons.lang.text.StrSubstitutor;
24 import org.apache.maven.plugin.ContextEnabled;
25 import org.apache.maven.plugin.MojoExecutionException;
26 import org.apache.maven.plugin.MojoFailureException;
27 import org.apache.maven.plugins.annotations.Execute;
28 import org.apache.maven.plugins.annotations.LifecyclePhase;
29 import org.apache.maven.plugins.annotations.Mojo;
30 import org.apache.maven.plugins.annotations.Parameter;
31 import java.io.File;
32 import java.io.IOException;
33 import java.io.InputStream;
34
35 import java.io.FileOutputStream;
36 import java.io.FileInputStream;
37 import java.nio.file.attribute.BasicFileAttributeView;
38 import java.nio.file.attribute.BasicFileAttributes;
39 import java.nio.file.Files;
40 import java.nio.file.Paths;
41 import java.net.URL;
42 import java.net.URISyntaxException;
43 import java.text.SimpleDateFormat;
44 import java.util.Date;
45 import java.util.Map;
46 import java.util.Collection;
47 import java.util.HashMap;
48 import java.util.jar.JarFile;
49 import java.util.jar.JarEntry;
50 import java.util.Enumeration;
51 import java.util.regex.Pattern;
52
53 import org.apache.commons.io.FileUtils;
54 import org.apache.commons.io.filefilter.TrueFileFilter;
55
56 import org.apache.maven.plugin.cxx.utils.svn.SvnService;
57 import org.apache.maven.plugin.cxx.utils.svn.SvnInfo;
58
59
60
61
62
63
64
65
66
67 @Mojo( name = "generate", requiresProject = false )
68 @Execute( phase = LifecyclePhase.GENERATE_SOURCES )
69 public class GenerateMojo
70 extends AbstractCxxMojo
71 implements ContextEnabled
72 {
73
74
75
76
77
78
79 @Parameter( property = "archetypeArtifactId", defaultValue = "cmake-cpp-project" )
80 private String archetypeArtifactId;
81
82
83
84
85
86
87 @Parameter( property = "archetypeGroupId", defaultValue = "org.apache.maven.plugin.cxx" )
88 private String archetypeGroupId;
89
90
91
92
93
94 @Parameter( property = "archetypeVersion", defaultValue = "0.1" )
95 private String archetypeVersion;
96
97
98
99
100
101
102 @Parameter( property = "parentGroupId", defaultValue = "fr.neticoa" )
103 private String parentGroupId;
104
105
106
107
108
109
110 @Parameter( property = "parentArtifactId", defaultValue = "cpp-super-pom" )
111 private String parentArtifactId;
112
113
114
115
116
117
118 @Parameter( property = "parentVersion", defaultValue = "1.1.0.0" )
119 private String parentVersion;
120
121
122
123
124
125
126 @Parameter( property = "groupId", defaultValue = "fr.neticoa" )
127 private String groupId;
128
129
130
131
132
133
134 @Parameter( property = "artifactName", required = true )
135 private String artifactName;
136
137
138
139
140
141
142 @Parameter( property = "artifactId", required = true )
143 private String artifactId;
144
145
146
147
148
149
150 @Parameter( property = "version", defaultValue = "0.0.0.1" )
151 private String version;
152
153
154
155
156
157
158 @Parameter( property = "cmakeMinVersion", defaultValue = "3.0.0" )
159 private String cmakeMinVersion;
160
161 protected Map<String, String> listResourceFolderContent( String path, Map valuesMap )
162 {
163 String location = getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
164 final File jarFile = new File( location );
165
166 HashMap<String, String> resources = new HashMap<String, String>();
167 StrSubstitutor substitutor = new StrSubstitutor( valuesMap );
168
169 path = ( StringUtils.isEmpty( path ) ) ? "" : path + "/";
170 getLog().debug( "listResourceFolderContent : " + location + ", sublocation : " + path );
171 if ( jarFile.isFile() )
172 {
173 getLog().debug( "listResourceFolderContent : jar case" );
174 try
175 {
176 final JarFile jar = new JarFile( jarFile );
177 final Enumeration<JarEntry> entries = jar.entries();
178 while ( entries.hasMoreElements() )
179 {
180 final String name = entries.nextElement().getName();
181 if ( name.startsWith( path ) )
182 {
183 String resourceFile = File.separator + name;
184 if ( !( resourceFile.endsWith( "/" ) || resourceFile.endsWith( "\\" ) ) )
185 {
186 getLog().debug( "resource entry = " + resourceFile );
187 String destFile = substitutor.replace( resourceFile );
188 getLog().debug( "become entry = " + destFile );
189 resources.put( resourceFile, destFile );
190 }
191 }
192 }
193 jar.close();
194 }
195 catch ( IOException ex )
196 {
197 getLog().error( "unable to list jar content : " + ex );
198 }
199 }
200 else
201 {
202 getLog().debug( "listResourceFolderContent : file case" );
203
204 final URL url = getClass().getResource( "/" + path );
205 if ( url != null )
206 {
207 try
208 {
209 final File names = new File( url.toURI() );
210 Collection<File> entries =
211 FileUtils.listFiles( names, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE );
212 for ( File name : entries )
213 {
214 String resourceFile = name.getPath();
215 if ( !( resourceFile.endsWith( "/" ) || resourceFile.endsWith( "\\" ) ) )
216 {
217 getLog().debug( "resource entry = " + resourceFile );
218 String destFile = substitutor.replace( resourceFile );
219 destFile = destFile.replaceFirst( Pattern.quote( location ), "/" );
220 getLog().debug( "become entry = " + destFile );
221 resources.put( resourceFile, destFile );
222 }
223 }
224 }
225 catch ( URISyntaxException ex )
226 {
227
228 }
229 }
230 }
231 return resources;
232 }
233
234 @Override
235 public void execute()
236 throws MojoExecutionException, MojoFailureException
237 {
238
239
240
241
242 org.apache.maven.artifact.versioning.DefaultArtifactVersion defautCMakeVersion =
243 new org.apache.maven.artifact.versioning.DefaultArtifactVersion( "3.0.0" );
244 org.apache.maven.artifact.versioning.DefaultArtifactVersion askedCMakeVersion =
245 new org.apache.maven.artifact.versioning.DefaultArtifactVersion( cmakeMinVersion );
246 boolean bCMake3OrAbove = ( askedCMakeVersion.compareTo( defautCMakeVersion ) >= 0 );
247
248 getLog().debug( "CMake 3 or above asked (" + cmakeMinVersion + ") ? " + ( bCMake3OrAbove ? "yes" : "no" ) );
249
250 HashMap<String, String> valuesMap = new HashMap<String, String>();
251 valuesMap.put( "parentGroupId", parentGroupId );
252 valuesMap.put( "parentArtifactId", parentArtifactId );
253 valuesMap.put( "parentVersion", parentVersion );
254 valuesMap.put( "groupId", groupId );
255 valuesMap.put( "artifactId", artifactId );
256 valuesMap.put( "artifactName", artifactName );
257 valuesMap.put( "version", version );
258 valuesMap.put( "cmakeMinVersion", cmakeMinVersion );
259 valuesMap.put( "parentScope", bCMake3OrAbove ? "PARENT_SCOPE" : "" );
260 valuesMap.put( "projectVersion", bCMake3OrAbove ? "VERSION ${TARGET_VERSION}" : "" );
261 valuesMap.put( "scmConnection", "" );
262
263
264
265
266 if ( StringUtils.isEmpty( archetypeArtifactId ) )
267 {
268 throw new MojoExecutionException( "archetypeArtifactId is empty " );
269 }
270
271 Map<String, String> resources = listResourceFolderContent( archetypeArtifactId, valuesMap );
272
273 if ( null == resources || resources.size() == 0 )
274 {
275 throw new MojoExecutionException( "Unable to find archetype : " + archetypeArtifactId );
276 }
277
278
279 SvnInfo basedirSvnInfo = SvnService.getSvnInfo( basedir, null, basedir.getAbsolutePath(), getLog(), true );
280 if ( basedirSvnInfo.isValide() )
281 {
282 valuesMap.put( "scmConnection", "scm:svn:" + basedirSvnInfo.getSvnUrl() );
283 }
284
285
286
287 getLog().info( "archetype " + archetypeArtifactId + " has " + resources.entrySet().size() + " item(s)" );
288 getLog().info( "basedir = " + basedir );
289
290 StrSubstitutor substitutor = new StrSubstitutor( valuesMap, "$(", ")" );
291 String sExecutionDate = new SimpleDateFormat( "yyyy-MM-dd-HH:mm:ss.SSS" ).format( new Date() );
292 for ( Map.Entry<String, String> entry : resources.entrySet() )
293 {
294 String curRes = entry.getKey();
295 String curDest = entry.getValue();
296 InputStream resourceStream = null;
297 resourceStream = getClass().getResourceAsStream( curRes );
298 if ( null == resourceStream )
299 {
300 try
301 {
302 resourceStream = new FileInputStream( new File( curRes ) );
303 }
304 catch ( Exception e )
305 {
306
307 resourceStream = null;
308 }
309 }
310
311 getLog().debug( "resource stream to open : " + curRes );
312 getLog().debug( "destfile pattern : " + curDest );
313 if ( null != resourceStream )
314 {
315 String sRelativePath = curDest.replaceFirst( Pattern.quote( archetypeArtifactId
316 + File.separator ), "" );
317 File newFile = new File( basedir + File.separator + sRelativePath );
318
319
320
321 File newDirs = new File( newFile.getParent() );
322 if ( Files.notExists( Paths.get( newDirs.getPath() ) ) )
323 {
324 getLog().info( "dirs to generate : " + newDirs.getAbsoluteFile() );
325 newDirs.mkdirs();
326 }
327
328 if ( !newFile.getName().equals( "empty.dir" ) )
329 {
330 getLog().info( "file to generate : " + newFile.getAbsoluteFile() );
331 try
332 {
333 if ( !newFile.createNewFile() )
334 {
335
336 FileInputStream inStream = new FileInputStream( newFile );
337 File backFile = File.createTempFile( newFile.getName() + ".",
338 "." + sExecutionDate + ".back", newFile.getParentFile() );
339 FileOutputStream outStream = new FileOutputStream( backFile );
340
341 IOUtils.copy( inStream, outStream );
342
343
344 BasicFileAttributes attributesFrom =
345 Files.getFileAttributeView( Paths.get( newFile.getPath() ),
346 BasicFileAttributeView.class ).readAttributes();
347 BasicFileAttributeView attributesToView =
348 Files.getFileAttributeView( Paths.get( backFile.getPath() ),
349 BasicFileAttributeView.class );
350 attributesToView.setTimes(
351 attributesFrom.lastModifiedTime(),
352 attributesFrom.lastAccessTime(),
353 attributesFrom.creationTime() );
354
355 inStream.close();
356 outStream.close();
357 }
358 FileOutputStream outStream = new FileOutputStream( newFile );
359
360
361
362
363 String content = IOUtils.toString( resourceStream, "UTF8" );
364 content = substitutor.replace( content );
365
366
367 IOUtils.write( content, outStream, "UTF8" );
368
369 outStream.close();
370 resourceStream.close();
371 }
372 catch ( IOException e )
373 {
374 getLog().error( "File " + newFile.getAbsoluteFile() + " can't be created : " + e );
375 }
376 }
377 }
378 else
379 {
380 getLog().error( "Unable to open resource " + curRes );
381 }
382 }
383 }
384 }