View Javadoc

1   package org.codehaus.mojo.minijar;
2   
3   /*
4    * Copyright 2005 The Apache Software Foundation.
5    * 
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    * 
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.io.File;
20  import java.io.FileNotFoundException;
21  import java.io.FileOutputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.Iterator;
27  import java.util.Map;
28  import java.util.Set;
29  import java.util.jar.JarOutputStream;
30  
31  import org.apache.maven.artifact.Artifact;
32  import org.apache.maven.plugin.MojoExecutionException;
33  import org.apache.maven.project.MavenProjectHelper;
34  import org.codehaus.mojo.minijar.resource.ComponentsXmlHandler;
35  import org.codehaus.mojo.minijar.resource.LicenseHandler;
36  import org.vafer.dependency.Clazz;
37  import org.vafer.dependency.Console;
38  import org.vafer.dependency.resources.ResourceHandler;
39  import org.vafer.dependency.resources.Version;
40  import org.vafer.dependency.utils.Jar;
41  import org.vafer.dependency.utils.JarUtils;
42  
43  /**
44   * Creates an ueberjar including all dependencies into one jar.
45   *
46   * @goal ueberjar
47   * @requiresDependencyResolution compile
48   * @execute phase="package"
49   */
50  public final class UeberJarMojo
51      extends AbstractPluginMojo
52  {
53      /** @component */
54      private MavenProjectHelper projectHelper;
55  
56      /**
57       * Defines the pattern of the name of final ueber jar.
58       * Possible substitutions are [artifactId] [version] and [groupId].
59       * 
60       * @parameter expression="${name}" default-value="[artifactId]-[version]-ueber.jar"
61       */ 
62      protected String name;
63  	
64      /**
65       * Defines whether the original artifact should be include so that
66       * the ueberjar is basically self contained. If set to false the
67       * ueberjar will only include the dependencies of the project.
68       * 
69       * @parameter expression="${includeArtifact}" default-value="true"
70       */
71      private boolean includeArtifact;
72  
73      /**
74       * By default the new ueberjar gets attached as an additional
75       * artifact. If you want to replace the orignal artifact set
76       * this to true.
77       * 
78       * @parameter expression="${replaceArtifact}" default-value="false"
79       */
80      private boolean replaceArtifact;
81  
82      
83      private final ResourceHandler[] handlers = {
84      	new LicenseHandler(),
85      	new ComponentsXmlHandler()
86      };
87  
88      
89      private InputStream handle( Jar jar, String oldName, String newName, Version[] versions, InputStream inputStream )
90  		throws IOException
91  	{
92  		InputStream is = inputStream;
93  		for (int i = 0; i < handlers.length; i++)
94  		{
95  			if ( is == null )
96  			{
97  				return null;
98  			}
99  
100 			is = handlers[i].onResource( jar, oldName, newName, versions, is );			
101 		}
102 		return is;
103     }
104     
105     /**
106      * Creates a combine jar of the dependencies and (as configured) also the build artifact
107      *
108      * @param pRemovable Set of classes that can be removed
109      * @throws MojoExecutionException on error
110      */
111     public void execute( final Set pRemovable, final Set pDependencies, final Set pRelocateDependencies )
112         throws MojoExecutionException
113     {
114         final Set artifacts = new HashSet(pDependencies);
115 
116         final Artifact projectArtifact = getProject().getArtifact();
117 
118         if ( includeArtifact )
119         {
120             getLog().info( "Including project artifact." );
121             artifacts.add( projectArtifact );
122         }
123         
124         final Jar[] jars = new Jar[ artifacts.size() ];
125 
126         final Iterator it = artifacts.iterator();
127         for (int i = 0; i < jars.length; i++)
128         {
129             final Artifact artifact = (Artifact) it.next();
130             final File file = artifact.getFile();
131             
132             try {
133             	final Jar jar = new Jar( file, artifact != projectArtifact );
134             	
135 				jars[i] = jar; 				
136 			}
137             catch ( FileNotFoundException e )
138             {
139 				throw new MojoExecutionException( "Could not locate jar " + file, e );
140 			}            
141         }
142 
143         final Map variables = new HashMap();
144         variables.put( "artifactId", projectArtifact.getArtifactId() );
145         variables.put( "groupId", projectArtifact.getGroupId() );
146         variables.put( "version", projectArtifact.getVersion() );
147 
148         final String newName = replaceVariables( variables, name );
149 
150         final File outputJar = new File( buildDirectory, newName );
151         
152         try
153         {
154             JarUtils.processJars(
155             		jars,
156             		new ResourceHandler() {
157 
158 						public void onStartProcessing( JarOutputStream pOutput )
159 							throws IOException
160 						{
161 							for (int i = 0; i < handlers.length; i++)
162 							{
163 								handlers[i].onStartProcessing( pOutput );								
164 							}
165 						}
166 
167 						public void onStartJar( Jar jar, JarOutputStream pOutput )
168 							throws IOException
169 						{
170 								for (int i = 0; i < handlers.length; i++)
171 								{
172 									handlers[i].onStartJar( jar, pOutput );								
173 								}
174 						}
175 
176 						public InputStream onResource( Jar jar, String oldName, String newName, Version[] versions, InputStream inputStream )
177 							throws IOException
178 						{
179 							
180 							if ( jar != versions[0].getJar() )
181 							{
182 								// only process the first version of it
183 								return null;
184 							}
185 							
186 							
187 							if ( !oldName.endsWith( ".class" ) )
188 							{
189 								return handle( jar, oldName, newName, versions, inputStream );
190 	        				}
191 
192 							final String clazzName = oldName.replace( '/' , '.' ).substring( 0, oldName.length() - ".class".length() );
193 							
194 							if (pRemovable.contains(new Clazz ( clazzName )))
195 							{
196 								// FIXME: artifact not available
197 //								if (isInKeepUnusedClassesFromArtifacts( artifact ) )
198 //								{
199 //									return handle( jar, oldName, newName, versions, inputStream );
200 //								}
201 
202 								if ( isInKeepUnusedClasses( name ) )
203 								{
204 									return handle( jar, oldName, newName, versions, inputStream );
205 								}
206 
207 								return null;
208 							}
209 							
210 							return handle( jar, oldName, newName, versions, inputStream );
211 						}
212 
213 						public void onStopJar( Jar pJar, JarOutputStream pOutput )
214 							throws IOException
215 						{
216 								for (int i = 0; i < handlers.length; i++)
217 								{
218 									handlers[i].onStopJar( pJar, pOutput );								
219 								}
220 						}
221 
222 						public void onStopProcessing( JarOutputStream pOutput )
223 							throws IOException
224 						{
225 								for (int i = 0; i < handlers.length; i++)
226 								{
227 									handlers[i].onStopProcessing( pOutput );								
228 								}
229 						}
230             			
231             		},
232             		new FileOutputStream( outputJar ),
233             		new Console()
234             		{
235             			public void println( String pString )
236             			{
237             				getLog().debug( pString );
238             			}            	
239             		}
240             	);
241         }
242         catch ( Exception e )
243         {
244             throw new MojoExecutionException( "Could not create combined output jar " + outputJar, e );
245         }
246 
247 		if ( replaceArtifact )
248 		{
249 			getLog().info( "Replacing artifact." );
250 			outputJar.renameTo( projectArtifact.getFile() );
251 		}
252 		else
253 		{
254 			getLog().info( "Attaching artifact." );
255 			projectHelper.attachArtifact( getProject(), "jar", "ueber", outputJar );
256 		}
257     }
258 
259 }