1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.apache.maven.plugin.eclipse.writers;
15
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.util.Arrays;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.Set;
24 import java.util.jar.Attributes;
25 import java.util.jar.Manifest;
26
27 import org.apache.maven.artifact.repository.ArtifactRepository;
28 import org.apache.maven.plugin.MojoExecutionException;
29 import org.apache.maven.plugin.eclipse.Constants;
30 import org.apache.maven.plugin.eclipse.EclipseSourceDir;
31 import org.apache.maven.plugin.eclipse.Messages;
32 import org.apache.maven.plugin.eclipse.writers.wtp.AbstractWtpResourceWriter;
33 import org.apache.maven.plugin.ide.IdeDependency;
34 import org.apache.maven.plugin.ide.IdeUtils;
35 import org.apache.maven.plugin.ide.JeeUtils;
36 import org.apache.maven.plugin.logging.Log;
37 import org.apache.maven.project.MavenProject;
38
39
40
41
42
43
44
45
46
47 public class EclipseManifestWriter
48 extends AbstractEclipseWriter
49 {
50
51 private static final String MANIFEST_MF_FILENAME = "MANIFEST.MF";
52
53 private static final String META_INF_DIRECTORY = "META-INF";
54
55 private static final String GENERATED_RESOURCE_DIRNAME =
56 "target" + File.separatorChar + "generated-resources" + File.separatorChar + "eclipse";
57
58 private static final String WEBAPP_RESOURCE_DIR =
59 "src" + File.separatorChar + "main" + File.separatorChar + "webapp";
60
61
62
63
64
65
66
67
68
69 private static String getWebContentBaseDirectory( EclipseWriterConfig config )
70 throws MojoExecutionException
71 {
72
73 File warSourceDirectory =
74 new File( IdeUtils.getPluginSetting( config.getProject(), JeeUtils.ARTIFACT_MAVEN_WAR_PLUGIN,
75 "warSourceDirectory", WEBAPP_RESOURCE_DIR ) );
76
77 String webContentDir =
78 IdeUtils.toRelativeAndFixSeparator( config.getEclipseProjectDirectory(), warSourceDirectory, false );
79
80
81 String result = config.getProject().getBasedir().getAbsolutePath() + File.separatorChar + webContentDir;
82
83 return result;
84 }
85
86
87
88
89
90
91
92 public String getMetaInfBaseDirectory( MavenProject project )
93 throws MojoExecutionException
94 {
95 String metaInfBaseDirectory = null;
96
97 if ( this.config.getProject().getPackaging().equals( Constants.PROJECT_PACKAGING_WAR ) )
98 {
99
100
101 metaInfBaseDirectory = getWebContentBaseDirectory( this.config );
102
103 this.log.debug( "Attempting to use: " + metaInfBaseDirectory + " for location of META-INF in war project." );
104
105 File metaInfDirectoryFile =
106 new File( metaInfBaseDirectory + File.separatorChar + EclipseManifestWriter.META_INF_DIRECTORY );
107
108 if ( !metaInfDirectoryFile.exists()
109 || ( metaInfDirectoryFile.exists() && !metaInfDirectoryFile.isDirectory() ) )
110 {
111 metaInfBaseDirectory = null;
112 }
113 }
114
115 for ( int index = this.config.getSourceDirs().length - 1; metaInfBaseDirectory == null && index >= 0; index-- )
116 {
117
118 File manifestFile =
119 new File( this.config.getEclipseProjectDirectory(), this.config.getSourceDirs()[index].getPath()
120 + File.separatorChar + EclipseManifestWriter.META_INF_DIRECTORY + File.separatorChar
121 + EclipseManifestWriter.MANIFEST_MF_FILENAME );
122
123 this.log.debug( "Checking for existence of META-INF/MANIFEST.MF file: " + manifestFile );
124
125 if ( manifestFile.exists() )
126 {
127 metaInfBaseDirectory = manifestFile.getParentFile().getParent();
128 }
129 }
130
131 return metaInfBaseDirectory;
132 }
133
134
135
136
137
138
139
140
141
142
143
144 public void write()
145 throws MojoExecutionException
146 {
147 File manifestFile = null;
148 String metaInfBaseDirectory = getMetaInfBaseDirectory( this.config.getProject() );
149
150 if ( metaInfBaseDirectory == null )
151 {
152
153 throw new MojoExecutionException(
154 Messages.getString(
155 "EclipseCleanMojo.nofilefound",
156 new Object[] { EclipseManifestWriter.META_INF_DIRECTORY } ) );
157 }
158 manifestFile =
159 new File( metaInfBaseDirectory + File.separatorChar + EclipseManifestWriter.META_INF_DIRECTORY
160 + File.separatorChar + EclipseManifestWriter.MANIFEST_MF_FILENAME );
161 Manifest manifest = createNewManifest();
162
163 log.info( "MANIFEST LOCATION: " + manifestFile );
164
165 if ( shouldNewManifestFileBeWritten( manifest, manifestFile ) )
166 {
167 log.info( "Writing manifest..." );
168
169 manifestFile.getParentFile().mkdirs();
170
171 try
172 {
173 FileOutputStream stream = new FileOutputStream( manifestFile );
174
175 manifest.write( stream );
176
177 stream.close();
178
179 }
180 catch ( Exception e )
181 {
182 this.log.error( Messages.getString( "EclipsePlugin.cantwritetofile",
183 new Object[] { manifestFile.getAbsolutePath() } ) );
184 }
185 }
186 }
187
188
189
190
191
192
193
194 public static void addManifestResource( Log log, EclipseWriterConfig config )
195 throws MojoExecutionException
196 {
197
198 EclipseManifestWriter manifestWriter = new EclipseManifestWriter();
199 manifestWriter.init( log, config );
200
201 String packaging = config.getProject().getPackaging();
202
203 String manifestDirectory = manifestWriter.getMetaInfBaseDirectory( config.getProject() );
204
205 if ( !Constants.PROJECT_PACKAGING_EAR.equals( packaging )
206 && !Constants.PROJECT_PACKAGING_WAR.equals( packaging ) && manifestDirectory == null )
207 {
208
209 String generatedResourceDir =
210 config.getProject().getBasedir().getAbsolutePath() + File.separatorChar
211 + EclipseManifestWriter.GENERATED_RESOURCE_DIRNAME;
212
213 manifestDirectory = generatedResourceDir + File.separatorChar + "META-INF";
214
215 try
216 {
217 new File( manifestDirectory ).mkdirs();
218 File manifestFile = new File( manifestDirectory + File.separatorChar + "MANIFEST.MF" );
219 if ( manifestFile.exists() )
220 {
221 manifestFile.delete();
222 }
223 manifestFile.createNewFile();
224 }
225 catch ( IOException e )
226 {
227 log.error( Messages.getString( "EclipsePlugin.cantwritetofile", new Object[] { manifestDirectory
228 + File.separatorChar + "META-INF" + File.separatorChar + "MANIFEST.MF" } ) );
229 }
230
231 log.debug( "Adding " + EclipseManifestWriter.GENERATED_RESOURCE_DIRNAME + " to eclipse sources " );
232
233 EclipseSourceDir[] sourceDirs = config.getSourceDirs();
234 EclipseSourceDir[] newSourceDirs = new EclipseSourceDir[sourceDirs.length + 1];
235 System.arraycopy( sourceDirs, 0, newSourceDirs, 0, sourceDirs.length );
236 newSourceDirs[sourceDirs.length] =
237 new EclipseSourceDir( EclipseManifestWriter.GENERATED_RESOURCE_DIRNAME, null, true, false, null, null,
238 false );
239 config.setSourceDirs( newSourceDirs );
240 }
241
242 if ( Constants.PROJECT_PACKAGING_WAR.equals( packaging ) )
243 {
244 new File( getWebContentBaseDirectory( config ) + File.separatorChar + "META-INF" ).mkdirs();
245 }
246
247
248
249
250 manifestWriter.write();
251 }
252
253
254
255
256
257
258
259
260
261 private void addDependencyToClassPath( StringBuffer classpath, IdeDependency dependency )
262 {
263 if ( !dependency.isTestDependency() && !dependency.isProvided()
264 && !dependency.isSystemScopedOutsideProject( this.config.getProject() ) )
265 {
266
267
268 if ( classpath.length() != 0 )
269 {
270 classpath.append( ' ' );
271 }
272
273
274 if ( !dependency.isReferencedProject() )
275 {
276 classpath.append( dependency.getFile().getName() );
277 }
278 else
279 {
280 classpath.append( dependency.getEclipseProjectName() + ".jar" );
281 }
282 }
283 }
284
285
286
287
288
289
290
291
292
293
294 private boolean areManifestsEqual( Manifest manifest, Manifest existingManifest )
295 {
296 if ( existingManifest == null )
297 {
298 return false;
299 }
300
301 Set keys = new HashSet();
302 Attributes existingMap = existingManifest.getMainAttributes();
303 Attributes newMap = manifest.getMainAttributes();
304 keys.addAll( existingMap.keySet() );
305 keys.addAll( newMap.keySet() );
306 Iterator iterator = keys.iterator();
307 while ( iterator.hasNext() )
308 {
309 Attributes.Name key = (Attributes.Name) iterator.next();
310 String newValue = (String) newMap.get( key );
311 String existingValue = (String) existingMap.get( key );
312
313
314 if ( Attributes.Name.CLASS_PATH.equals( key ) )
315 {
316 newValue = orderClasspath( newValue );
317 existingValue = orderClasspath( existingValue );
318 }
319 if ( ( newValue == null || !newValue.equals( existingValue ) )
320 && ( existingValue == null || !existingValue.equals( newValue ) ) )
321 {
322 return false;
323 }
324 }
325 return true;
326 }
327
328
329
330
331
332
333 private String constructManifestClasspath()
334 {
335 StringBuffer stringBuffer = new StringBuffer();
336 IdeDependency[] deps = this.config.getDepsOrdered();
337
338 for ( int index = 0; index < deps.length; index++ )
339 {
340 addDependencyToClassPath( stringBuffer, deps[index] );
341 }
342
343 return stringBuffer.toString();
344 }
345
346
347
348
349
350
351 private Manifest createNewManifest()
352 {
353 Manifest manifest = new Manifest();
354 manifest.getMainAttributes().put( Attributes.Name.MANIFEST_VERSION, "1.0" );
355 manifest.getMainAttributes().put( Attributes.Name.CLASS_PATH, constructManifestClasspath() );
356 return manifest;
357 }
358
359
360
361
362
363
364
365 private String orderClasspath( String newValue )
366 {
367 if ( newValue == null )
368 {
369 return null;
370 }
371 String[] entries = newValue.split( " " );
372 Arrays.sort( entries );
373 StringBuffer buffer = new StringBuffer( newValue.length() );
374 for ( int index = 0; index < entries.length; index++ )
375 {
376 buffer.append( entries[index] );
377 buffer.append( ' ' );
378 }
379 return buffer.toString();
380 }
381
382
383
384
385
386
387
388
389 private Manifest readExistingManifest( File manifestFile )
390 throws IOException
391 {
392 if ( !manifestFile.exists() )
393 {
394 return null;
395 }
396
397 Manifest existingManifest = new Manifest();
398 FileInputStream inputStream = new FileInputStream( manifestFile );
399 existingManifest.read( inputStream );
400 inputStream.close();
401 return existingManifest;
402 }
403
404
405
406
407
408
409
410
411
412
413 private boolean shouldNewManifestFileBeWritten( Manifest manifest, File manifestFile )
414 throws MojoExecutionException
415 {
416 try
417 {
418 Manifest existingManifest = readExistingManifest( manifestFile );
419 if ( areManifestsEqual( manifest, existingManifest ) )
420 {
421 this.log.info( Messages.getString( "EclipseCleanMojo.unchanged", manifestFile.getAbsolutePath() ) );
422 return false;
423 }
424 }
425 catch ( Exception e )
426 {
427 throw new MojoExecutionException( Messages.getString( "EclipseCleanMojo.nofilefound",
428 manifestFile.getAbsolutePath() ), e );
429 }
430 return true;
431 }
432 }