View Javadoc

1   package org.codehaus.mojo.apt;
2   
3   /*
4    * The MIT License
5    *
6    * Copyright 2006-2008 The Codehaus.
7    *
8    * Permission is hereby granted, free of charge, to any person obtaining a copy of
9    * this software and associated documentation files (the "Software"), to deal in
10   * the Software without restriction, including without limitation the rights to
11   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12   * of the Software, and to permit persons to whom the Software is furnished to do
13   * so, subject to the following conditions:
14   *
15   * The above copyright notice and this permission notice shall be included in all
16   * copies or substantial portions of the Software.
17   *
18   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24   * SOFTWARE.
25   */
26  
27  import java.io.File;
28  import java.io.FileWriter;
29  import java.io.IOException;
30  import java.io.PrintWriter;
31  import java.io.StringReader;
32  import java.io.StringWriter;
33  import java.lang.reflect.InvocationTargetException;
34  import java.lang.reflect.Method;
35  import java.util.List;
36  
37  import org.apache.maven.plugin.MojoExecutionException;
38  import org.apache.maven.plugin.logging.Log;
39  import org.codehaus.plexus.util.IOUtil;
40  import org.codehaus.plexus.util.StringUtils;
41  import org.codehaus.plexus.util.cli.CommandLineException;
42  import org.codehaus.plexus.util.cli.CommandLineUtils;
43  import org.codehaus.plexus.util.cli.Commandline;
44  import org.codehaus.plexus.util.cli.CommandLineUtils.StringStreamConsumer;
45  
46  /**
47   * Provides methods of invoking the Annotation Processing Tool (apt) compiler.
48   * 
49   * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
50   * @version $Id: AptUtils.java 11286 2009-11-21 16:02:42Z bentmann $
51   */
52  public final class AptUtils
53  {
54      // constants --------------------------------------------------------------
55  
56      /**
57       * The line separator for the current platform.
58       */
59      private static final String LINE_SEPARATOR = System.getProperty( "line.separator" );
60  
61      // fields -----------------------------------------------------------------
62  
63      // constructors -----------------------------------------------------------
64  
65      private AptUtils()
66      {
67          throw new AssertionError();
68      }
69  
70      // public methods ---------------------------------------------------------
71  
72      public static boolean invoke( Log log, List<String> args ) throws MojoExecutionException
73      {
74          // get apt method
75  
76          Class<?> apt = getAptClass();
77  
78          StringWriter stringWriter = new StringWriter();
79          PrintWriter writer = new PrintWriter( stringWriter, true );
80          String[] argsArray = args.toArray( new String[args.size()] );
81  
82          Method method;
83          Object[] methodArgs;
84  
85          try
86          {
87              method = apt.getMethod( "process", new Class[] { PrintWriter.class, String[].class } );
88  
89              methodArgs = new Object[] { writer, argsArray };
90          }
91          catch ( NoSuchMethodException exception )
92          {
93              try
94              {
95                  method = apt.getMethod( "compile", new Class[] { String[].class, PrintWriter.class } );
96  
97                  methodArgs = new Object[] { argsArray, writer };
98              }
99              catch ( NoSuchMethodException exception2 )
100             {
101                 throw new MojoExecutionException( "Error while executing the apt compiler", exception2 );
102             }
103         }
104 
105         // invoke apt
106 
107         log.debug( "Invoking apt with arguments:" );
108         LogUtils.log( log, LogUtils.LEVEL_DEBUG, args, "  " );
109 
110         int result;
111 
112         try
113         {
114             result = ( (Integer) method.invoke( null, methodArgs ) ).intValue();
115         }
116         catch ( IllegalAccessException exception )
117         {
118             throw new MojoExecutionException( "Error while executing the apt compiler", exception );
119         }
120         catch ( InvocationTargetException exception )
121         {
122             throw new MojoExecutionException( "Error while executing the apt compiler", exception );
123         }
124 
125         // log output
126 
127         LogUtils.log( log, LogUtils.LEVEL_WARN, new StringReader( stringWriter.toString() ) );
128 
129         // log result
130 
131         log.debug( "Apt returned " + result );
132 
133         return ( result == 0 );
134     }
135 
136     public static boolean invokeForked( Log log, File workingDirectory, String executable, String meminitial,
137                                         String maxmemory, List<String> args ) throws MojoExecutionException
138     {
139         // create command
140 
141         Commandline cli = new Commandline();
142 
143         cli.setWorkingDirectory( workingDirectory.getAbsolutePath() );
144         log.debug( "Using working directory " + cli.getWorkingDirectory() );
145 
146         cli.setExecutable( executable );
147 
148         if ( StringUtils.isNotEmpty( meminitial ) )
149         {
150             cli.createArg().setValue( "-J-Xms" + meminitial );
151         }
152 
153         if ( StringUtils.isNotEmpty( maxmemory ) )
154         {
155             cli.createArg().setValue( "-J-Xmx" + maxmemory );
156         }
157 
158         // create arguments file
159 
160         File argsFile;
161 
162         try
163         {
164             argsFile = createArgsFile( args );
165 
166             String argsPath = argsFile.getCanonicalPath().replace( File.separatorChar, '/' );
167             cli.createArg().setValue( "@" + argsPath );
168         }
169         catch ( IOException exception )
170         {
171             throw new MojoExecutionException( "Error creating arguments file", exception );
172         }
173 
174         log.debug( "Using argument file:" );
175         LogUtils.log( log, LogUtils.LEVEL_DEBUG, argsFile, "  " );
176 
177         // invoke apt
178 
179         if ( log.isDebugEnabled() )
180         {
181             log.debug( "Invoking apt with command " + cli );
182         }
183 
184         StringStreamConsumer out = new StringStreamConsumer();
185         StringStreamConsumer err = new StringStreamConsumer();
186 
187         int result;
188 
189         try
190         {
191             result = CommandLineUtils.executeCommandLine( cli, out, err );
192         }
193         catch ( CommandLineException exception )
194         {
195             throw new MojoExecutionException( "Error while executing the apt compiler", exception );
196         }
197 
198         // log output
199 
200         LogUtils.log( log, LogUtils.LEVEL_INFO, new StringReader( out.getOutput() ) );
201         LogUtils.log( log, LogUtils.LEVEL_WARN, new StringReader( err.getOutput() ) );
202 
203         // log result
204 
205         log.debug( "Apt returned " + result );
206 
207         return ( result == 0 );
208     }
209 
210     // private methods --------------------------------------------------------
211 
212     private static Class<?> getAptClass() throws MojoExecutionException
213     {
214         try
215         {
216             return Class.forName( "com.sun.tools.apt.Main", true, AptClassLoader.INSTANCE );
217         }
218         catch ( ClassNotFoundException exception )
219         {
220             throw new MojoExecutionException( "Unable to locate the apt compiler in:" + LINE_SEPARATOR
221                 + "  " + AptClassLoader.getToolsJar() + LINE_SEPARATOR
222                 + "Please ensure you are using JDK 1.5 or above and" + LINE_SEPARATOR
223                 + "not a JRE (the com.sun.tools.apt.Main class is required)." + LINE_SEPARATOR
224                 + "In most cases you can change the location of your Java" + LINE_SEPARATOR
225                 + "installation by setting the JAVA_HOME environment variable." );
226         }
227     }
228 
229     private static File createArgsFile( List<String> args ) throws IOException
230     {
231         File file = File.createTempFile( AptUtils.class.getName(), ".argfile" );
232         file.deleteOnExit();
233 
234         PrintWriter writer = null;
235 
236         try
237         {
238             writer = new PrintWriter( new FileWriter( file ) );
239 
240             for ( String arg : args )
241             {
242                 arg = arg.replace( File.separatorChar, '/' );
243 
244                 if ( arg.contains( " " ) )
245                 {
246                     arg = "\"" + arg + "\"";
247                 }
248 
249                 writer.println( arg );
250             }
251         }
252         finally
253         {
254             IOUtil.close( writer );
255         }
256 
257         return file;
258     }
259 }