1 package org.codehaus.mojo.minijar;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.Map;
24 import java.util.Set;
25
26 import org.apache.maven.artifact.Artifact;
27 import org.apache.maven.plugin.AbstractMojo;
28 import org.apache.maven.plugin.MojoExecutionException;
29 import org.apache.maven.project.MavenProject;
30 import org.vafer.dependency.Clazzpath;
31 import org.vafer.dependency.ClazzpathUnit;
32
33
34
35
36 public abstract class AbstractPluginMojo
37 extends AbstractMojo
38 {
39
40
41
42
43
44 private MavenProject project;
45
46
47
48
49
50
51
52
53 protected File buildDirectory;
54
55
56
57
58
59
60
61
62
63
64 protected HashSet includeDependenciesInRelocation = null;
65
66
67
68
69
70
71
72
73 protected HashSet excludeDependenciesInRelocation = null;
74
75
76
77
78
79
80
81
82
83
84 protected HashSet includeDependencies = null;
85
86
87
88
89
90
91
92
93 protected HashSet excludeDependencies = null;
94
95
96
97
98
99
100
101
102
103
104
105
106 protected boolean stripUnusedClasses;
107
108
109
110
111
112
113
114
115
116 protected HashSet keepUnusedClassesFromArtifacts = new HashSet();
117
118
119
120
121
122
123
124
125 protected HashSet keepUnusedClasses = new HashSet();
126
127
128 protected MavenProject getProject()
129 {
130 if ( project.getExecutionProject() != null )
131 {
132 return project.getExecutionProject();
133 }
134 else
135 {
136 return project;
137 }
138 }
139
140
141
142
143
144
145
146
147
148 protected String replaceVariables( final Map pVariables, final String pExpression )
149 {
150
151 final char[] s = pExpression.toCharArray();
152
153 final char[] open = "[".toCharArray();
154 final char[] close = "]".toCharArray();
155
156 final StringBuffer out = new StringBuffer();
157 StringBuffer sb = new StringBuffer();
158 char[] watch = open;
159 int w = 0;
160 for (int i = 0; i < s.length; i++)
161 {
162 char c = s[i];
163
164 if ( c == watch[w] )
165 {
166 w++;
167 if (watch.length == w)
168 {
169 if(watch == open)
170 {
171
172 out.append( sb );
173 sb = new StringBuffer();
174 watch = close;
175 }
176 else if ( watch == close )
177 {
178
179 final String variable = (String) pVariables.get( sb.toString() );
180 if ( variable != null )
181 {
182 out.append( variable );
183 }
184 else
185 {
186 getLog().error( "Unknown variable " + sb );
187 }
188 sb = new StringBuffer();
189 watch = open;
190 }
191 w = 0;
192 }
193 }
194 else
195 {
196 if (w > 0 )
197 {
198 sb.append( watch, 0, w );
199 }
200
201 sb.append( c );
202
203 w = 0;
204 }
205 }
206
207 if ( watch == open )
208 {
209 out.append( sb );
210 }
211
212 return out.toString();
213 }
214
215
216 public boolean isInKeepUnusedClassesFromArtifacts( final Artifact artifact ) {
217
218 final String id = artifact.getGroupId() + ":" + artifact.getArtifactId();
219
220 return keepUnusedClassesFromArtifacts.contains(id);
221 }
222
223 public boolean isInKeepUnusedClasses( final String clazzname ) {
224
225
226
227 return keepUnusedClasses.contains(clazzname);
228 }
229
230
231
232
233
234
235
236 private Set getArtifactsFromIds( final Set artifacts, final Set ids )
237 {
238 if ( ids == null )
239 {
240 return null;
241 }
242
243 final Set result = new HashSet();
244
245 for ( Iterator it = artifacts.iterator(); it.hasNext(); )
246 {
247 final Artifact artifact = (Artifact) it.next();
248
249 final String id = artifact.getGroupId() + ":" + artifact.getArtifactId();
250
251 if ( ids.contains( id ) )
252 {
253 result.add( artifact );
254 }
255 }
256
257 return result;
258 }
259
260
261 private Set combine( final Set all, final Set included, final Set excluded, final Set defaults )
262 {
263 final Set result = new HashSet();
264
265 if ( excluded != null )
266 {
267 result.addAll(all);
268 result.removeAll(excluded);
269 }
270
271 if ( included != null )
272 {
273 result.addAll(included);
274 }
275
276 if ( excluded == null && included == null)
277 {
278 result.addAll(defaults);
279 }
280
281 return result;
282 }
283
284
285 public abstract void execute( final Set removable, final Set dependencies, final Set relocateDependencies )
286 throws MojoExecutionException;
287
288
289
290
291
292
293 public void execute()
294 throws MojoExecutionException
295 {
296 final Set removable = new HashSet();
297
298
299 if ( excludeDependencies != null && excludeDependencies.size() == 0 )
300 {
301 excludeDependencies = null;
302 }
303 if ( includeDependencies != null && includeDependencies.size() == 0 )
304 {
305 includeDependencies = null;
306 }
307 if ( excludeDependenciesInRelocation != null && excludeDependenciesInRelocation.size() == 0 )
308 {
309 excludeDependenciesInRelocation = null;
310 }
311 if ( includeDependenciesInRelocation != null && includeDependenciesInRelocation.size() == 0 )
312 {
313 includeDependenciesInRelocation = null;
314 }
315
316
317 if ( excludeDependencies != null && includeDependencies != null ) {
318 throw new MojoExecutionException( "Both parameters excludeDependencies and includeDependencies are mutual exclusive" );
319 }
320
321 if ( excludeDependenciesInRelocation != null && includeDependenciesInRelocation != null ) {
322 throw new MojoExecutionException( "Both parameters excludeDependenciesInRelocation and includeDependenciesInRelocation are mutual exclusive" );
323 }
324
325 final Set projectArtifacts = getProject().getArtifacts();
326
327 final Set dependencies = combine(
328 projectArtifacts,
329 getArtifactsFromIds( projectArtifacts, includeDependencies ),
330 getArtifactsFromIds( projectArtifacts, excludeDependencies ),
331 projectArtifacts
332 );
333
334 final Set relocateDependencies = combine(
335 projectArtifacts,
336 getArtifactsFromIds( projectArtifacts, includeDependenciesInRelocation ),
337 getArtifactsFromIds( projectArtifacts, excludeDependenciesInRelocation ),
338 projectArtifacts
339 );
340
341 getLog().debug( "dependencies: " + dependencies );
342 getLog().debug( "relocateDependencies: " + relocateDependencies );
343
344 if ( stripUnusedClasses )
345 {
346 getLog().info( "Calculating transitive hull of class dependencies." );
347
348 try
349 {
350 final Artifact projectArtifact = getProject().getArtifact();
351
352 if ( projectArtifact == null )
353 {
354 throw new MojoExecutionException( "No project artifact" );
355 }
356
357 final File projectArtifactFile = projectArtifact.getFile();
358
359 if ( projectArtifactFile == null )
360 {
361 throw new MojoExecutionException( "No project artifact file" );
362 }
363
364 final Clazzpath clazzpath = new Clazzpath();
365 final ClazzpathUnit jar = new ClazzpathUnit( clazzpath, projectArtifactFile.getAbsolutePath() );
366
367 for ( Iterator i = project.getArtifacts().iterator(); i.hasNext(); )
368 {
369 final Artifact dependency = (Artifact) i.next();
370
371 if ( !dependencies.contains( dependency ) )
372 {
373 getLog().info( "Ignoring " + dependency );
374 continue;
375 }
376
377 new ClazzpathUnit( clazzpath, dependency.getFile().getAbsolutePath() );
378 }
379
380 removable.addAll( clazzpath.getClazzes() );
381
382 final int total = removable.size();
383
384 removable.removeAll( jar.getClazzes() );
385 removable.removeAll( jar.getTransitiveDependencies() );
386
387 getLog().info( "Can remove " + removable.size() + " of " + total + " classes (" + (int) ( 100 * removable.size() / total ) + "%)." );
388
389
390
391 }
392 catch ( IOException e )
393 {
394 throw new MojoExecutionException( "Could not analyse classpath dependencies", e );
395 }
396 }
397
398 execute( removable, dependencies, relocateDependencies );
399 }
400
401 }