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