View Javadoc

1   package org.apache.maven.shared.utils.cli.javatool;
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.shared.utils.Os;
23  import org.apache.maven.shared.utils.StringUtils;
24  import org.apache.maven.shared.utils.cli.CommandLineException;
25  import org.apache.maven.shared.utils.cli.CommandLineUtils;
26  import org.apache.maven.shared.utils.cli.Commandline;
27  import org.apache.maven.shared.utils.cli.StreamConsumer;
28  import org.apache.maven.toolchain.Toolchain;
29  import org.codehaus.plexus.logging.AbstractLogEnabled;
30  
31  import java.io.File;
32  import java.io.InputStream;
33  import java.util.Map;
34  
35  /**
36   * Abstract implementation of a {@link JavaTool}.
37   *
38   * @author Tony Chemit <chemit@codelutin.com>
39   * @since 0.5
40   */
41  public abstract class AbstractJavaTool<Request extends JavaToolRequest>
42      extends AbstractLogEnabled
43      implements JavaTool<Request>
44  {
45  
46      /**
47       * The java tool name to find out in the jdk.
48       */
49      private final String javaToolName;
50  
51      /**
52       * The location of the java tool executable file.
53       */
54      private String javaToolFile;
55  
56      /**
57       * Optional toolChain used to find java tool executable file.
58       */
59      private Toolchain toolchain;
60  
61      protected AbstractJavaTool( String javaToolName )
62      {
63          this.javaToolName = javaToolName;
64      }
65  
66      /**
67       * Create the commandline object given the request.
68       *
69       * @param request      User request on the java tool
70       * @param javaToolFile Location of the java tool file to use
71       * @return the commandline
72       * @throws JavaToolException if could not create the command line from the request
73       */
74      protected abstract Commandline createCommandLine( Request request, String javaToolFile )
75          throws JavaToolException;
76  
77      /**
78       * {@inheritDoc}
79       */
80      public String getJavaToolName()
81      {
82          return javaToolName;
83      }
84  
85      /**
86       * {@inheritDoc}
87       */
88      public void setToolchain( Toolchain toolchain )
89      {
90          this.toolchain = toolchain;
91      }
92  
93      /**
94       * {@inheritDoc}
95       */
96      public JavaToolResult execute( Request request )
97          throws JavaToolException
98      {
99  
100         if ( javaToolFile == null )
101         {
102 
103             // find the java tool file to use
104             try
105             {
106                 javaToolFile = findJavaToolExecutable();
107             }
108             catch ( Exception e )
109             {
110                 throw new JavaToolException( "Error finding " + javaToolName + " executable. Reason: " + e.getMessage(),
111                                              e );
112             }
113         }
114 
115         // creates the command line from the given request
116         Commandline cli = createCommandLine( request, javaToolFile );
117 
118         // execute it
119         JavaToolResult result = executeCommandLine( cli, request );
120 
121         // return result
122         return result;
123     }
124 
125     protected InputStream createSystemInputStream()
126     {
127         InputStream systemIn = new InputStream()
128         {
129 
130             /**
131              * {@inheritDoc}
132              */
133             public int read()
134             {
135                 return -1;
136             }
137 
138         };
139         return systemIn;
140     }
141 
142     protected JavaToolResult executeCommandLine( Commandline cli, Request request )
143     {
144         if ( getLogger().isDebugEnabled() )
145         {
146             getLogger().debug( "Executing: " + cli );
147         }
148 
149         JavaToolResult result = createResult();
150 
151         result.setCommandline( cli );
152 
153         InputStream systemIn = createSystemInputStream();
154 
155         StreamConsumer systemOut = createSystemOutStreamConsumer( request );
156 
157         StreamConsumer systemErr = createSystemErrorStreamConsumer( request );
158 
159         try
160         {
161             int resultCode = CommandLineUtils.executeCommandLine( cli, systemIn, systemOut, systemErr );
162 
163             result.setExitCode( resultCode );
164         }
165         catch ( CommandLineException e )
166         {
167             result.setExecutionException( e );
168         }
169 
170         return result;
171     }
172 
173     protected StreamConsumer createSystemErrorStreamConsumer( Request request )
174     {
175         StreamConsumer systemErr = request.getSystemErrorStreamConsumer();
176 
177         if ( systemErr == null )
178         {
179             systemErr = new StreamConsumer()
180             {
181 
182                 /**
183                  * {@inheritDoc}
184                  */
185                 public void consumeLine( final String line )
186                 {
187                     getLogger().warn( line );
188                 }
189 
190             };
191         }
192         return systemErr;
193     }
194 
195     protected StreamConsumer createSystemOutStreamConsumer( Request request )
196     {
197         StreamConsumer systemOut = request.getSystemOutStreamConsumer();
198 
199         if ( systemOut == null )
200         {
201 
202             systemOut = new StreamConsumer()
203             {
204 
205                 /**
206                  * {@inheritDoc}
207                  */
208                 public void consumeLine( final String line )
209                 {
210                     getLogger().info( line );
211 
212                 }
213 
214             };
215         }
216         return systemOut;
217     }
218 
219     protected JavaToolResult createResult()
220     {
221         return new JavaToolResult();
222     }
223 
224     protected String findJavaToolExecutable()
225     {
226         String command = javaToolName + ( Os.isFamily( Os.FAMILY_WINDOWS ) ? ".exe" : "" );
227 
228         String executable = null;
229 
230         if ( toolchain != null )
231         {
232             executable = toolchain.findTool( javaToolName );
233         }
234 
235         if ( executable == null )
236         {
237             executable = findExecutable( command, System.getProperty( "java.home" ), "../bin", "bin", "../sh" );
238         }
239 
240         if ( executable == null )
241         {
242 
243             Map<String, String> env = System.getenv();
244 
245             String[] variables = { "JDK_HOME", "JAVA_HOME" };
246 
247             for ( String variable : variables )
248             {
249                 executable = findExecutable( command, env.get( variable ), "bin", "sh" );
250                 if ( executable != null )
251                 {
252                     break;
253                 }
254             }
255         }
256 
257         if ( executable == null )
258         {
259             executable = command;
260         }
261 
262         return executable;
263     }
264 
265     /**
266      * Finds the specified command in any of the given sub directories of the specified JDK/JRE home directory.
267      *
268      * @param command The command to find, must not be <code>null</code>.
269      * @param homeDir The home directory to search in, may be <code>null</code>.
270      * @param subDirs The sub directories of the home directory to search in, must not be <code>null</code>.
271      * @return The (absolute) path to the command if found, <code>null</code> otherwise.
272      */
273     private String findExecutable( String command, String homeDir, String... subDirs )
274     {
275         String result = null;
276         if ( StringUtils.isNotEmpty( homeDir ) )
277         {
278             for ( String subDir : subDirs )
279             {
280                 File file = new File( new File( homeDir, subDir ), command );
281 
282                 if ( file.isFile() )
283                 {
284                     result = file.getAbsolutePath();
285                     break;
286                 }
287             }
288         }
289 
290         return result;
291     }
292 }