View Javadoc
1   package org.codehaus.mojo.gwt.shell;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.plugin.logging.Log;
23  import org.codehaus.plexus.util.StringUtils;
24  import org.codehaus.plexus.util.cli.CommandLineException;
25  import org.codehaus.plexus.util.cli.CommandLineTimeOutException;
26  import org.codehaus.plexus.util.cli.CommandLineUtils;
27  import org.codehaus.plexus.util.cli.Commandline;
28  import org.codehaus.plexus.util.cli.StreamConsumer;
29  
30  import java.io.File;
31  import java.util.ArrayList;
32  import java.util.Collection;
33  import java.util.Collections;
34  import java.util.List;
35  import java.util.Map;
36  import java.util.Properties;
37  
38  /**
39   * @author <a href="mailto:olamy@apache.org">Olivier Lamy</a>
40   * @since 2.1.0-1
41   */
42  public class JavaCommand
43  {
44      private String mainClass;
45  
46      private List<File> classpath = new ArrayList<File>();
47  
48      private List<String> args = new ArrayList<String>();
49  
50      private Properties systemProperties = new Properties();
51  
52      private Properties env = new Properties();
53  
54      private List<String> jvmArgs;
55  
56      private String jvm;
57  
58      private Log log;
59  
60      private int timeOut;
61  
62      private List<ClassPathProcessor> classPathProcessors = new ArrayList<ClassPathProcessor>();
63  
64      /**
65       * A plexus-util StreamConsumer to redirect messages to plugin log
66       */
67      private StreamConsumer out = new StreamConsumer()
68      {
69          public void consumeLine( String line )
70          {
71              log.info( line );
72          }
73      };
74  
75      /**
76       * A plexus-util StreamConsumer to redirect errors to plugin log
77       */
78      private StreamConsumer err = new StreamConsumer()
79      {
80          public void consumeLine( String line )
81          {
82              log.error( line );
83          }
84      };
85  
86      /**
87       * Indicates whether to print the full command (as part of exception message) when encountering error.
88       */
89      private boolean printCommandOnError = true;
90  
91      public String getMainClass()
92      {
93          return mainClass;
94      }
95  
96      public JavaCommand setMainClass( String mainClass )
97      {
98          this.mainClass = mainClass;
99          return this;
100     }
101 
102     public List<File> getClasspath()
103     {
104         return classpath;
105     }
106 
107     public JavaCommand setClasspath( List<File> classpath )
108     {
109         this.classpath = classpath;
110         return this;
111     }
112 
113     public List<String> getArgs()
114     {
115         return args;
116     }
117 
118     public JavaCommand setArgs( List<String> args )
119     {
120         this.args = args;
121         return this;
122     }
123 
124     public Properties getSystemProperties()
125     {
126         return systemProperties;
127     }
128 
129     public JavaCommand setSystemProperties( Properties systemProperties )
130     {
131         this.systemProperties = systemProperties;
132         return this;
133     }
134 
135     public Properties getEnv()
136     {
137         return env;
138     }
139 
140     public JavaCommand setEnv( Properties env )
141     {
142         this.env = env;
143         return this;
144     }
145 
146     public List<String> getJvmArgs()
147     {
148         if (this.jvmArgs == null)
149         {
150             this.jvmArgs = new ArrayList<String>();
151         }
152         return jvmArgs;
153     }
154 
155     public JavaCommand setJvmArgs( List<String> jvmArgs )
156     {
157         this.jvmArgs = jvmArgs;
158         return this;
159     }
160 
161     public String getJvm()
162     {
163         return jvm;
164     }
165 
166     public JavaCommand setJvm( String jvm )
167     {
168         this.jvm = jvm;
169         return this;
170     }
171 
172     public Log getLog()
173     {
174         return log;
175     }
176 
177     public JavaCommand setLog( Log log )
178     {
179         this.log = log;
180         return this;
181     }
182 
183     public int getTimeOut()
184     {
185         return timeOut;
186     }
187 
188     public JavaCommand setTimeOut( int timeOut )
189     {
190         this.timeOut = timeOut;
191         return this;
192     }
193 
194     public List<ClassPathProcessor> getClassPathProcessors()
195     {
196         return classPathProcessors;
197     }
198 
199     public JavaCommand addClassPathProcessors( ClassPathProcessor classPathProcessor )
200     {
201         classPathProcessors.add( classPathProcessor );
202         return this;
203     }
204 
205     public JavaCommand setClassPathProcessors( List<ClassPathProcessor> classPathProcessors )
206     {
207         this.classPathProcessors = classPathProcessors;
208         return this;
209     }
210 
211     public JavaCommand setOut( StreamConsumer out )
212     {
213         this.out = out;
214         return this;
215     }
216 
217     public void setPrintCommandOnError( boolean printCommandOnError ) {
218         this.printCommandOnError = printCommandOnError;
219     }
220 
221     public JavaCommand addToClasspath( File file )
222     {
223         return addToClasspath( Collections.singleton( file ) );
224     }
225 
226     public JavaCommand addToClasspath( Collection<File> elements )
227     {
228         classpath.addAll( elements );
229         return this;
230     }
231 
232     public JavaCommand prependToClasspath( Collection<File> elements )
233     {
234         classpath.addAll( 0, elements );
235         return this;
236     }
237 
238     public JavaCommand arg( String arg )
239     {
240         args.add( arg );
241         return this;
242     }
243 
244     public JavaCommand arg( String arg, String value )
245     {
246         args.add( arg );
247         args.add( value );
248         return this;
249     }
250 
251     public JavaCommand arg( boolean condition, String arg )
252     {
253         if ( condition )
254         {
255             args.add( arg );
256         }
257         return this;
258     }
259 
260     public JavaCommand systemProperty( String name, String value )
261     {
262         systemProperties.setProperty( name, value );
263         return this;
264     }
265 
266     public JavaCommand environment( String name, String value )
267     {
268         env.setProperty( name, value );
269         return this;
270     }
271 
272     public void execute()
273         throws JavaCommandException
274     {
275         for (ClassPathProcessor classPathProcessor : classPathProcessors )
276         {
277             classPathProcessor.postProcessClassPath( classpath );
278         }
279 
280         List<String> command = new ArrayList<String>();
281         if (this.jvmArgs != null)
282         {
283             command.addAll( this.jvmArgs );
284         }
285         if ( systemProperties != null )
286         {
287             for ( Map.Entry<?, ?> entry : systemProperties.entrySet() )
288             {
289                 command.add( "-D" + entry.getKey() + "=" + entry.getValue() );
290             }
291         }
292         command.add( mainClass );
293         command.addAll( args );
294 
295         List<String> path = new ArrayList<String>( classpath.size() );
296         for ( File file : classpath ) path.add( file.getAbsolutePath() );
297         String classpath = StringUtils.join( path.iterator(), File.pathSeparator );
298 
299         try
300         {
301             String[] arguments = command.toArray( new String[command.size()] );
302 
303             Commandline cmd = new Commandline();
304             cmd.setExecutable( this.getJavaCommand() );
305             cmd.addEnvironment( "CLASSPATH", classpath );
306             cmd.addArguments( arguments );
307             if ( env != null )
308             {
309                 for ( Map.Entry<?, ?> entry : env.entrySet() )
310                 {
311                     log.debug( "add env " + (String) entry.getKey() + " with value " + (String) entry.getValue() );
312                     cmd.addEnvironment( (String) entry.getKey(), (String) entry.getValue() );
313                 }
314             }
315             log.debug( "Execute command :\n" + cmd.toString() );
316             log.debug( "With CLASSPATH :\n" + classpath );
317             int status = CommandLineUtils.executeCommandLine( cmd, out, err, timeOut );
318 
319             if ( status != 0 )
320             {
321                 throw new JavaCommandException( "Command failed with status "  + status
322                         + (printCommandOnError ? ":\n" + cmd : "" ) );
323             }
324         }
325         catch ( CommandLineTimeOutException e )
326         {
327             throw new JavaCommandException(
328                     "Time-out on command line execution" + (printCommandOnError ? ":\n" + command : ""), e );
329         }
330         catch ( CommandLineException e )
331         {
332             throw new JavaCommandException(
333                     "Failed to execute command line" + (printCommandOnError ? ":\n" + command : ""), e );
334         }
335     }
336 
337     private String getJavaCommand()
338         throws JavaCommandException
339     {
340         if ( StringUtils.isEmpty( jvm ) )
341         {
342             // use the same JVM as the one used to run Maven (the "java.home" one)
343             jvm = System.getProperty( "java.home" );
344         }
345 
346         // does-it exists ? is-it a directory or a path to a java executable ?
347         File jvmFile = new File( jvm );
348         if ( !jvmFile.exists() )
349         {
350             throw new JavaCommandException( "the configured jvm " + jvm
351                 + " doesn't exists please check your environment" );
352         }
353         if ( jvmFile.isDirectory() )
354         {
355             // it's a directory we construct the path to the java executable
356             return jvmFile.getAbsolutePath() + File.separator + "bin" + File.separator + "java";
357         }
358         log.debug( "use jvm " + jvm );
359         return jvm;
360     }
361 }