View Javadoc

1   package org.apache.continuum.installation;
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.continuum.dao.InstallationDao;
23  import org.apache.maven.continuum.execution.ExecutorConfigurator;
24  import org.apache.maven.continuum.installation.AlreadyExistsInstallationException;
25  import org.apache.maven.continuum.installation.InstallationException;
26  import org.apache.maven.continuum.installation.InstallationService;
27  import org.apache.maven.continuum.model.system.Installation;
28  import org.apache.maven.continuum.model.system.Profile;
29  import org.apache.maven.continuum.profile.AlreadyExistsProfileException;
30  import org.apache.maven.continuum.profile.ProfileException;
31  import org.apache.maven.continuum.profile.ProfileService;
32  import org.apache.maven.continuum.store.ContinuumStoreException;
33  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
34  import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
35  import org.codehaus.plexus.util.StringUtils;
36  import org.codehaus.plexus.util.cli.CommandLineException;
37  import org.codehaus.plexus.util.cli.CommandLineUtils;
38  import org.codehaus.plexus.util.cli.Commandline;
39  import org.codehaus.plexus.util.cli.StreamConsumer;
40  import org.slf4j.Logger;
41  import org.slf4j.LoggerFactory;
42  import org.springframework.stereotype.Service;
43  
44  import java.io.File;
45  import java.io.IOException;
46  import java.util.ArrayList;
47  import java.util.Collections;
48  import java.util.HashMap;
49  import java.util.List;
50  import java.util.Map;
51  import java.util.Properties;
52  import javax.annotation.Resource;
53  
54  /**
55   * @author <a href="mailto:olamy@codehaus.org">olamy</a>
56   * @version $Id: DefaultInstallationService.java 1372260 2012-08-13 04:29:09Z brett $
57   *          TODO use some cache mechanism to prevent always reading from store ?
58   * @since 13 juin 07
59   */
60  @Service( "installationService" )
61  public class DefaultInstallationService
62      implements InstallationService, Initializable
63  {
64      private static final Logger log = LoggerFactory.getLogger( DefaultInstallationService.class );
65  
66      @Resource
67      private InstallationDao installationDao;
68  
69      @Resource
70      private ProfileService profileService;
71  
72      private Map<String, ExecutorConfigurator> typesValues;
73  
74      // ---------------------------------------------
75      // Plexus lifecycle
76      // ---------------------------------------------
77  
78      public void initialize()
79          throws InitializationException
80      {
81          this.typesValues = new HashMap<String, ExecutorConfigurator>();
82          this.typesValues.put( InstallationService.ANT_TYPE, new ExecutorConfigurator( "ant", "bin", "ANT_HOME",
83                                                                                        "-version" ) );
84  
85          this.typesValues.put( InstallationService.ENVVAR_TYPE, null );
86          this.typesValues.put( InstallationService.JDK_TYPE, new ExecutorConfigurator( "java", "bin", "JAVA_HOME",
87                                                                                        "-version" ) );
88          this.typesValues.put( InstallationService.MAVEN1_TYPE, new ExecutorConfigurator( "maven", "bin", "MAVEN_HOME",
89                                                                                           "-v" ) );
90          this.typesValues.put( InstallationService.MAVEN2_TYPE, new ExecutorConfigurator( "mvn", "bin", "M2_HOME",
91                                                                                           "-v" ) );
92      }
93  
94      /**
95       * @see org.apache.maven.continuum.installation.InstallationService#add(org.apache.maven.continuum.model.system.Installation)
96       */
97      public Installation add( Installation installation )
98          throws InstallationException, AlreadyExistsInstallationException
99      {
100         try
101         {
102             return this.add( installation, false );
103         }
104         catch ( AlreadyExistsProfileException e )
105         {
106             // normally cannot happend here but anyway we throw the exception
107             throw new InstallationException( e.getMessage(), e );
108         }
109     }
110 
111     public Installation add( Installation installation, boolean automaticProfile )
112         throws InstallationException, AlreadyExistsProfileException, AlreadyExistsInstallationException
113     {
114         if ( alreadyExistInstallationName( installation ) )
115         {
116             throw new AlreadyExistsInstallationException(
117                 "Installation with name " + installation.getName() + " already exists" );
118         }
119         // TODO must be done in the same transaction
120         Installation storedOne;
121         try
122         {
123             String envVarName = this.getEnvVar( installation.getType() );
124             // override with the defined var name for defined types
125             if ( StringUtils.isNotEmpty( envVarName ) )
126             {
127                 installation.setVarName( envVarName );
128             }
129             storedOne = installationDao.addInstallation( installation );
130         }
131         catch ( ContinuumStoreException e )
132         {
133             throw new InstallationException( e.getMessage(), e );
134         }
135         try
136         {
137             if ( automaticProfile )
138             {
139                 Profile profile = new Profile();
140                 profile.setName( storedOne.getName() );
141                 profile = profileService.addProfile( profile );
142                 profileService.addInstallationInProfile( profile, storedOne );
143             }
144         }
145         catch ( ProfileException e )
146         {
147             throw new InstallationException( "failed to create automatic Profile " + e.getMessage(), e );
148         }
149         return storedOne;
150     }
151 
152     /**
153      * @see org.apache.maven.continuum.installation.InstallationService#delete(org.apache.maven.continuum.model.system.Installation)
154      */
155     public void delete( Installation installation )
156         throws InstallationException
157     {
158         try
159         {
160             installationDao.removeInstallation( installation );
161         }
162         catch ( ContinuumStoreException e )
163         {
164             throw new InstallationException( e.getMessage(), e );
165         }
166 
167     }
168 
169     /**
170      * @see org.apache.maven.continuum.installation.InstallationService#getAllInstallations()
171      */
172     @SuppressWarnings( "unchecked" )
173     public List<Installation> getAllInstallations()
174         throws InstallationException
175     {
176         try
177         {
178             List<Installation> installations = installationDao.getAllInstallations();
179             return installations == null ? Collections.EMPTY_LIST : installations;
180         }
181         catch ( ContinuumStoreException e )
182         {
183             throw new InstallationException( e.getMessage(), e );
184         }
185     }
186 
187     /**
188      * @see org.apache.maven.continuum.installation.InstallationService#getInstallation(int)
189      */
190     public Installation getInstallation( int installationId )
191         throws InstallationException
192     {
193         try
194         {
195             return installationDao.getInstallation( installationId );
196         }
197         catch ( ContinuumStoreException e )
198         {
199             throw new InstallationException( e.getMessage(), e );
200         }
201     }
202 
203     /**
204      * @see org.apache.maven.continuum.installation.InstallationService#getInstallation(String)
205      */
206     public Installation getInstallation( String installationName )
207         throws InstallationException
208     {
209         try
210         {
211             return installationDao.getInstallation( installationName );
212         }
213         catch ( ContinuumStoreException e )
214         {
215             throw new InstallationException( e.getMessage(), e );
216         }
217     }
218 
219     /**
220      * @see org.apache.maven.continuum.installation.InstallationService#update(org.apache.maven.continuum.model.system.Installation)
221      */
222     public void update( Installation installation )
223         throws InstallationException, AlreadyExistsInstallationException
224     {
225         try
226         {
227             Installation stored = getInstallation( installation.getInstallationId() );
228             if ( stored == null )
229             {
230                 throw new InstallationException( "installation with name " + installation.getName() + " not exists" );
231             }
232 
233             stored.setName( installation.getName() );
234             if ( alreadyExistInstallationName( installation ) )
235             {
236                 throw new AlreadyExistsInstallationException(
237                     "Installation with name " + installation.getName() + " already exists" );
238             }
239             stored.setType( installation.getType() );
240             String envVarName = this.getEnvVar( installation.getType() );
241             // override with the defined var name for defined types
242             if ( StringUtils.isNotEmpty( envVarName ) )
243             {
244                 installation.setVarName( envVarName );
245             }
246             else
247             {
248                 stored.setVarName( installation.getVarName() );
249             }
250             stored.setVarValue( installation.getVarValue() );
251             installationDao.updateInstallation( stored );
252         }
253         catch ( ContinuumStoreException e )
254         {
255             throw new InstallationException( e.getMessage(), e );
256         }
257 
258     }
259 
260     /**
261      * @see org.apache.maven.continuum.installation.InstallationService#getExecutorConfigurator(java.lang.String)
262      */
263     public ExecutorConfigurator getExecutorConfigurator( String type )
264     {
265         return this.typesValues.get( type );
266     }
267 
268     /**
269      * @see org.apache.maven.continuum.installation.InstallationService#getEnvVar(java.lang.String)
270      */
271     public String getEnvVar( String type )
272     {
273         ExecutorConfigurator executorConfigurator = this.typesValues.get( type );
274         return executorConfigurator == null ? null : executorConfigurator.getEnvVar();
275     }
276 
277     // -------------------------------------------------------------
278     // versions informations on jdk and builders (mvn, maven, ant )
279     // -------------------------------------------------------------
280 
281     /**
282      * TODO replace with calling getExecutorConfiguratorVersion
283      *
284      * @see org.apache.maven.continuum.installation.InstallationService#getDefaultJdkInformations()
285      */
286     public List<String> getDefaultJdkInformations()
287         throws InstallationException
288     {
289         try
290         {
291             Properties systemEnvVars = CommandLineUtils.getSystemEnvVars( false );
292 
293             String javaHome = (String) systemEnvVars.get( "JAVA_HOME" );
294             // olamy : JAVA_HOME can not exists with a mac user
295             if ( StringUtils.isEmpty( javaHome ) )
296             {
297                 return getJavaHomeInformations( System.getProperty( "java.home" ) );
298             }
299             return getJavaHomeInformations( javaHome );
300 
301         }
302         catch ( IOException e )
303         {
304             throw new InstallationException( e.getMessage(), e );
305         }
306         catch ( CommandLineException e )
307         {
308             throw new InstallationException( e.getMessage(), e );
309         }
310     }
311 
312     /**
313      * TODO replace with calling getExecutorConfiguratorVersion
314      *
315      * @see org.apache.maven.continuum.installation.InstallationService#getJdkInformations(org.apache.maven.continuum.model.system.Installation)
316      */
317     public List<String> getJdkInformations( Installation installation )
318         throws InstallationException
319     {
320         if ( installation == null )
321         {
322             return getDefaultJdkInformations();
323         }
324         if ( StringUtils.isEmpty( installation.getVarValue() ) )
325         {
326             return getDefaultJdkInformations();
327         }
328         try
329         {
330             return getJavaHomeInformations( installation.getVarValue() );
331         }
332         catch ( CommandLineException e )
333         {
334             throw new InstallationException( e.getMessage(), e );
335         }
336     }
337 
338     /**
339      * @param javaHome
340      * @return
341      * @throws CommandLineException
342      */
343     private List<String> getJavaHomeInformations( String javaHome )
344         throws CommandLineException
345     {
346         Commandline commandline = new Commandline();
347 
348         String executable = javaHome + File.separator + "bin" + File.separator + "java";
349 
350         commandline.setExecutable( executable );
351         commandline.addArguments( new String[]{"-version"} );
352         final List<String> cliOutput = new ArrayList<String>();
353         //TODO ShellCommandHelper ?
354         int result = CommandLineUtils.executeCommandLine( commandline, new StreamConsumer()
355                                                           {
356                                                               public void consumeLine( String line )
357                                                               {
358                                                                   cliOutput.add( line );
359                                                               }
360                                                           }, new StreamConsumer()
361                                                           {
362                                                               public void consumeLine( String line )
363                                                               {
364                                                                   cliOutput.add( line );
365                                                               }
366                                                           }
367         );
368         if ( result != 0 )
369         {
370             throw new CommandLineException( "cli to get JAVA_HOME informations return code " + result );
371         }
372         return cliOutput;
373     }
374 
375     private Map<String, String> getEnvVars( Profile profile )
376     {
377         Map<String, String> environnments = new HashMap<String, String>();
378         if ( profile == null )
379         {
380             return environnments;
381         }
382         if ( profile.getBuilder() != null )
383         {
384             environnments.put( profile.getBuilder().getVarName(), profile.getBuilder().getVarValue() );
385         }
386         if ( profile.getJdk() != null )
387         {
388             environnments.put( profile.getJdk().getVarName(), profile.getJdk().getVarValue() );
389         }
390         if ( profile.getEnvironmentVariables() != null )
391         {
392             for ( Installation installation : (List<Installation>) profile.getEnvironmentVariables() )
393             {
394                 environnments.put( installation.getVarName(), installation.getVarValue() );
395             }
396         }
397         return environnments;
398     }
399 
400     /**
401      * @see org.apache.maven.continuum.installation.InstallationService#getExecutorConfiguratorVersion(java.lang.String, org.apache.maven.continuum.execution.ExecutorConfigurator, Profile)
402      */
403     @SuppressWarnings( "unchecked" )
404     public List<String> getExecutorConfiguratorVersion( String path, ExecutorConfigurator executorConfigurator,
405                                                         Profile profile )
406         throws InstallationException
407     {
408 
409         if ( executorConfigurator == null )
410         {
411             return Collections.EMPTY_LIST;
412         }
413         if ( executorConfigurator.getExecutable() == null )
414         {
415             return Collections.EMPTY_LIST;
416         }
417         StringBuilder executable = new StringBuilder();
418         try
419         {
420             Commandline commandline = new Commandline();
421             if ( StringUtils.isNotEmpty( path ) )
422             {
423                 executable.append( path ).append( File.separator );
424                 executable.append( executorConfigurator.getRelativePath() ).append( File.separator );
425                 commandline.addEnvironment( executorConfigurator.getEnvVar(), path );
426             }
427             //Installations are env var they must be add if exists
428             Map<String, String> environments = getEnvVars( profile );
429             // no null check we use a private method just here
430             for ( String key : environments.keySet() )
431             {
432                 String value = environments.get( key );
433                 commandline.addEnvironment( key, value );
434             }
435 
436             executable = executable.append( executorConfigurator.getExecutable() );
437             commandline.setExecutable( executable.toString() );
438             commandline.addArguments( new String[]{executorConfigurator.getVersionArgument()} );
439             final List<String> cliOutput = new ArrayList<String>();
440             //TODO ShellCommandHelper ?
441             int result = CommandLineUtils.executeCommandLine( commandline, new StreamConsumer()
442                                                               {
443                                                                   public void consumeLine( String line )
444                                                                   {
445                                                                       cliOutput.add( line );
446                                                                   }
447                                                               }, new StreamConsumer()
448                                                               {
449                                                                   public void consumeLine( String line )
450                                                                   {
451                                                                       cliOutput.add( line );
452                                                                   }
453                                                               }
454             );
455             if ( result != 0 )
456             {
457                 throw new InstallationException( "cli to get " + executable + " version return code " + result );
458             }
459             return cliOutput;
460         }
461         catch ( CommandLineException e )
462         {
463             log.error( "fail to execute " + executable + " with arg " + executorConfigurator.getVersionArgument() );
464             throw new InstallationException( e.getMessage(), e );
465         }
466     }
467 
468     private boolean alreadyExistInstallationName( Installation installation )
469         throws InstallationException
470     {
471         List<Installation> all = getAllInstallations();
472         for ( Installation install : all )
473         {
474             if ( org.apache.commons.lang.StringUtils.equals( installation.getName(), install.getName() ) &&
475                 ( installation.getInstallationId() == 0 ||
476                     installation.getInstallationId() != install.getInstallationId() ) )
477             {
478                 return true;
479             }
480         }
481         return false;
482     }
483 
484 }