View Javadoc

1   package org.apache.maven.shared.jarsigner;
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.codehaus.plexus.logging.AbstractLogEnabled;
23  import org.apache.maven.shared.utils.Os;
24  import org.apache.maven.shared.utils.StringUtils;
25  import org.apache.maven.shared.utils.cli.CommandLineException;
26  import org.apache.maven.shared.utils.cli.CommandLineUtils;
27  import org.apache.maven.shared.utils.cli.Commandline;
28  import org.apache.maven.shared.utils.cli.StreamConsumer;
29  
30  import java.io.File;
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.util.Map;
34  
35  /**
36   * Default implementation of component {@link JarSigner}.
37   *
38   * @author tchemit <chemit@codelutin.com>
39   * @version $Id: DefaultJarSigner.html 885985 2013-11-09 08:11:31Z tchemit $
40   * @plexus.component role="org.apache.maven.shared.jarsigner.JarSigner" role-hint="default"
41   * @since 1.0
42   */
43  public class DefaultJarSigner
44      extends AbstractLogEnabled
45      implements JarSigner
46  {
47  
48      /**
49       * The location of the jarSigner executable file.
50       */
51      protected String jarSignerFile;
52  
53      public JarSignerResult execute( JarSignerRequest request )
54          throws JarSignerException
55      {
56  
57          if ( jarSignerFile == null )
58          {
59  
60              // find the jar singer to use
61              try
62              {
63                  jarSignerFile = findJarSignerExecutable();
64              }
65              catch ( IOException e )
66              {
67                  throw new JarSignerException( "Error finding jar signer executable. Reason: " + e.getMessage(), e );
68              }
69          }
70  
71          // creates the command line
72          Commandline cli = createCommandLine( request );
73  
74          // execute it
75          return executeCommandLine( cli, request );
76      }
77  
78      protected Commandline createCommandLine( JarSignerRequest request )
79          throws JarSignerException
80      {
81          JarSignerCommandLineBuilder cliBuilder = new JarSignerCommandLineBuilder();
82          cliBuilder.setLogger( getLogger() );
83          cliBuilder.setJarSignerFile( jarSignerFile );
84          try
85          {
86              return cliBuilder.build( request );
87          }
88          catch ( CommandLineConfigurationException e )
89          {
90              throw new JarSignerException( "Error configuring command-line. Reason: " + e.getMessage(), e );
91          }
92      }
93  
94      protected JarSignerResult executeCommandLine( Commandline cli, JarSignerRequest request )
95      {
96          if ( getLogger().isDebugEnabled() )
97          {
98              getLogger().debug( "Executing: " + cli );
99          }
100 
101         final boolean verbose = request.isVerbose();
102 
103         InputStream systemIn = new InputStream()
104         {
105 
106             public int read()
107             {
108                 return -1;
109             }
110 
111         };
112         StreamConsumer systemOut = request.getSystemOutStreamConsumer();
113 
114         if ( systemOut == null )
115         {
116             systemOut = new StreamConsumer()
117             {
118 
119                 public void consumeLine( final String line )
120                 {
121                     if ( verbose )
122                     {
123                         getLogger().info( line );
124                     }
125                     else
126                     {
127                         getLogger().debug( line );
128                     }
129                 }
130 
131             };
132         }
133 
134         StreamConsumer systemErr = request.getSystemErrorStreamConsumer();
135 
136         if ( systemErr == null )
137         {
138             systemErr = new StreamConsumer()
139             {
140 
141                 public void consumeLine( final String line )
142                 {
143                     getLogger().warn( line );
144                 }
145 
146             };
147         }
148 
149         DefaultJarSignerResult result = new DefaultJarSignerResult();
150         result.setCommandline( cli );
151 
152         if ( verbose )
153         {
154             getLogger().info( cli.toString() );
155         }
156         else
157         {
158             getLogger().debug( cli.toString() );
159         }
160 
161         try
162         {
163             int resultCode = CommandLineUtils.executeCommandLine( cli, systemIn, systemOut, systemErr );
164 
165             result.setExitCode( resultCode );
166         }
167         catch ( CommandLineException e )
168         {
169             result.setExecutionException( e );
170         }
171 
172         return result;
173     }
174 
175     protected String findJarSignerExecutable()
176         throws IOException
177     {
178         String command = "jarsigner" + ( Os.isFamily( Os.FAMILY_WINDOWS ) ? ".exe" : "" );
179 
180         String executable =
181             findExecutable( command, System.getProperty( "java.home" ), new String[]{ "../bin", "bin", "../sh" } );
182 
183         if ( executable == null )
184         {
185 
186             Map<String, String> env = System.getenv();
187 
188             String[] variables = { "JDK_HOME", "JAVA_HOME" };
189 
190             for ( int i = 0; i < variables.length && executable == null; i++ )
191             {
192                 executable = findExecutable( command, env.get( variables[i] ), new String[]{ "bin", "sh" } );
193             }
194 
195         }
196 
197         if ( executable == null )
198         {
199             executable = command;
200         }
201 
202         return executable;
203     }
204 
205     /**
206      * Finds the specified command in any of the given sub directories of the specified JDK/JRE home directory.
207      *
208      * @param command The command to find, must not be <code>null</code>.
209      * @param homeDir The home directory to search in, may be <code>null</code>.
210      * @param subDirs The sub directories of the home directory to search in, must not be <code>null</code>.
211      * @return The (absolute) path to the command if found, <code>null</code> otherwise.
212      */
213     protected String findExecutable( String command, String homeDir, String[] subDirs )
214     {
215         if ( StringUtils.isNotEmpty( homeDir ) )
216         {
217             for ( int i = 0; i < subDirs.length; i++ )
218             {
219                 File file = new File( new File( homeDir, subDirs[i] ), command );
220 
221                 if ( file.isFile() )
222                 {
223                     return file.getAbsolutePath();
224                 }
225             }
226         }
227 
228         return null;
229     }
230 }