View Javadoc

1   package org.apache.maven.continuum.web.action;
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 java.io.File;
23  import java.io.IOException;
24  import java.io.UnsupportedEncodingException;
25  import java.net.MalformedURLException;
26  import java.net.URL;
27  import java.net.URLEncoder;
28  import java.util.ArrayList;
29  import java.util.Collection;
30  import java.util.List;
31  
32  import javax.servlet.http.HttpServletRequest;
33  
34  import org.apache.commons.io.FileUtils;
35  import org.apache.maven.continuum.ContinuumException;
36  import org.apache.maven.continuum.builddefinition.BuildDefinitionServiceException;
37  import org.apache.maven.continuum.model.project.BuildDefinitionTemplate;
38  import org.apache.maven.continuum.model.project.ProjectGroup;
39  import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
40  import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
41  import org.apache.struts2.interceptor.ServletRequestAware;
42  import org.codehaus.plexus.util.StringUtils;
43  
44  /**
45   * Action to add a Maven project to Continuum, either Maven 1 or Maven 2.
46   *
47   * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
48   * @version $Id: AddMavenProjectAction.java 781924 2009-06-05 06:42:54Z ctan $
49   */
50  public abstract class AddMavenProjectAction
51      extends ContinuumActionSupport
52      implements ServletRequestAware
53  {
54      private static final long serialVersionUID = -3965565189557706469L;
55  
56      private static final int DEFINED_BY_POM_GROUP_ID = -1;
57  
58      private String pomUrl;
59  
60      private File pomFile;
61  
62      private String pom = null;
63  
64      private String scmUsername;
65  
66      private String scmPassword;
67  
68      private Collection<ProjectGroup> projectGroups;
69  
70      private String projectGroupName;
71  
72      private int selectedProjectGroup = DEFINED_BY_POM_GROUP_ID;
73  
74      private boolean disableGroupSelection;
75  
76      private boolean scmUseCache;
77  
78      private int projectGroupId;
79  
80      private List<BuildDefinitionTemplate> buildDefinitionTemplates;
81  
82      private int buildDefinitionTemplateId;
83  
84      private List<String> errorMessages = new ArrayList<String>();
85  
86      private HttpServletRequest httpServletRequest;
87  
88      public String execute()
89          throws ContinuumException, BuildDefinitionServiceException
90      {
91          try
92          {
93              initializeProjectGroupName();
94  
95              if ( StringUtils.isEmpty( getProjectGroupName() ) )
96              {
97                  checkAddProjectGroupAuthorization();
98              }
99              else
100             {
101                 checkAddProjectToGroupAuthorization( getProjectGroupName() );
102             }
103         }
104         catch ( AuthorizationRequiredException authzE )
105         {
106             addActionError( authzE.getMessage() );
107             return REQUIRES_AUTHORIZATION;
108         }
109 
110         boolean checkProtocol = true;
111 
112         if ( !StringUtils.isEmpty( pomUrl ) )
113         {
114             try
115             {
116                 URL url = new URL( pomUrl );
117                 if ( pomUrl.startsWith( "http" ) && !StringUtils.isEmpty( scmUsername ) )
118                 {
119                     String encoding = this.httpServletRequest.getCharacterEncoding();
120                     if ( StringUtils.isEmpty( encoding ) )
121                     {
122                         encoding = System.getProperty( "file.encoding" );
123                     }
124 
125                     String encodedUsername = URLEncoder.encode( scmUsername, encoding );
126                     String encodedPassword = URLEncoder.encode( scmPassword, encoding );
127 
128                     StringBuffer urlBuffer = new StringBuffer();
129                     urlBuffer.append( url.getProtocol() ).append( "://" );
130                     urlBuffer.append( encodedUsername ).append( ':' ).append( encodedPassword ).append( '@' ).append(
131                         url.getHost() );
132                     if ( url.getPort() != -1 )
133                     {
134                         urlBuffer.append( ":" ).append( url.getPort() );
135                     }
136                     urlBuffer.append( url.getPath() );
137 
138                     pom = urlBuffer.toString();
139                 }
140                 else
141                 {
142                     pom = pomUrl;
143                 }
144             }
145             catch ( MalformedURLException e )
146             {
147                 addActionError( getText( "add.project.unknown.error" ) );
148                 return doDefault();
149             }
150             catch ( UnsupportedEncodingException e )
151             {
152                 addActionError( getText( "add.project.unknown.error" ) );
153                 return doDefault();
154             }
155 
156         }
157         else
158         {
159             if ( pomFile != null )
160             {
161                 try
162                 {
163                     //pom = pomFile.toURL().toString();
164                     checkProtocol = false;
165                     // CONTINUUM-1897
166                     // File.c copyFile to tmp one
167                     File tmpPom = File.createTempFile( "continuum_tmp", "tmp" );
168                     FileUtils.copyFile( pomFile, tmpPom );
169                     pom = tmpPom.toURL().toString();
170                 }
171                 catch ( MalformedURLException e )
172                 {
173                     // if local file can't be converted to url it's an internal error
174                     throw new RuntimeException( e );
175                 }
176                 catch ( IOException e )
177                 {
178                     throw new RuntimeException( e );
179                 }
180             }
181             else
182             {
183                 // no url or file was filled
184                 addActionError( getText( "add.project.field.required.error" ) );
185                 return doDefault();
186             }
187         }
188 
189         ContinuumProjectBuildingResult result = doExecute( pom, selectedProjectGroup, checkProtocol, scmUseCache );
190 
191         if ( result.hasErrors() )
192         {
193             for ( String key : result.getErrors() )
194             {
195                 String cause = result.getErrorsWithCause().get( key );
196                 String msg = getText( key, new String[]{cause} );
197 
198                 // olamy : weird getText(key, String[]) must do that something like bla bla {0}
199                 // here an ugly hack for CONTINUUM-1675
200                 if ( key.equals( ContinuumProjectBuildingResult.ERROR_MISSING_SCM ) )
201                 {
202                     msg = getResourceBundle().getString( key ) + " " + cause;
203                 }
204                 if ( !StringUtils.equals( msg, key ) )
205                 {
206                     errorMessages.add( msg );
207                 }
208                 else
209                 {
210                     addActionError( msg );
211                 }
212 
213             }
214 
215             return doDefault();
216         }
217 
218         if ( this.getSelectedProjectGroup() > 0 )
219         {
220             this.setProjectGroupId( this.getSelectedProjectGroup() );
221             return "projectGroupSummary";
222         }
223 
224         if ( result.getProjectGroups() != null && !result.getProjectGroups().isEmpty() )
225         {
226             this.setProjectGroupId( ( result.getProjectGroups().get( 0 ) ).getId() );
227             return "projectGroupSummary";
228         }
229 
230         return SUCCESS;
231     }
232 
233     /**
234      * Subclasses must implement this method calling the appropiate operation on the continuum service.
235      *
236      * @param pomUrl               url of the pom specified by the user
237      * @param selectedProjectGroup project group id selected by the user
238      * @param checkProtocol        check if the protocol is allowed, use false if the pom is uploaded
239      * @return result of adding the pom to continuum
240      */
241     protected abstract ContinuumProjectBuildingResult doExecute( String pomUrl, int selectedProjectGroup,
242                                                                  boolean checkProtocol, boolean scmUseCache )
243         throws ContinuumException;
244 
245     // TODO: Remove this method because a default method return SUCCESS instead of INPUT
246     public String doDefault()
247         throws BuildDefinitionServiceException
248     {
249         return input();
250     }
251 
252     public String input()
253         throws BuildDefinitionServiceException
254     {
255         try
256         {
257             initializeProjectGroupName();
258 
259             if ( StringUtils.isEmpty( getProjectGroupName() ) )
260             {
261                 checkAddProjectGroupAuthorization();
262             }
263             else
264             {
265                 checkAddProjectToGroupAuthorization( getProjectGroupName() );
266             }
267         }
268         catch ( AuthorizationRequiredException authzE )
269         {
270             addActionError( authzE.getMessage() );
271             return REQUIRES_AUTHORIZATION;
272         }
273         Collection<ProjectGroup> allProjectGroups = getContinuum().getAllProjectGroups();
274         projectGroups = new ArrayList<ProjectGroup>();
275 
276         ProjectGroup defaultGroup = new ProjectGroup();
277         defaultGroup.setId( DEFINED_BY_POM_GROUP_ID );
278         defaultGroup.setName( "Defined by POM" );
279         projectGroups.add( defaultGroup );
280 
281         for ( ProjectGroup pg : allProjectGroups )
282         {
283             if ( isAuthorizedToAddProjectToGroup( pg.getName() ) )
284             {
285                 projectGroups.add( pg );
286             }
287         }
288 
289         initializeProjectGroupName();
290         this.setBuildDefinitionTemplates( getContinuum().getBuildDefinitionService().getAllBuildDefinitionTemplate() );
291         return INPUT;
292     }
293 
294     protected String hidePasswordInUrl( String url )
295     {
296         int indexAt = url.indexOf( "@" );
297 
298         if ( indexAt < 0 )
299         {
300             return url;
301         }
302 
303         String s = url.substring( 0, indexAt );
304 
305         int pos = s.lastIndexOf( ":" );
306 
307         return s.substring( 0, pos + 1 ) + "*****" + url.substring( indexAt );
308     }
309 
310     private void initializeProjectGroupName()
311     {
312         if ( disableGroupSelection && selectedProjectGroup != DEFINED_BY_POM_GROUP_ID )
313         {
314             try
315             {
316                 projectGroupName = getContinuum().getProjectGroup( selectedProjectGroup ).getName();
317             }
318             catch ( ContinuumException e )
319             {
320                 e.printStackTrace();
321             }
322         }
323     }
324 
325     public String getPom()
326     {
327         return pom;
328     }
329 
330     public void setPom( String pom )
331     {
332         this.pom = pom;
333     }
334 
335     public File getPomFile()
336     {
337         return pomFile;
338     }
339 
340     public void setPomFile( File pomFile )
341     {
342         this.pomFile = pomFile;
343     }
344 
345     public String getPomUrl()
346     {
347         return pomUrl;
348     }
349 
350     public void setPomUrl( String pomUrl )
351     {
352         this.pomUrl = pomUrl;
353     }
354 
355     public void setScmPassword( String scmPassword )
356     {
357         this.scmPassword = scmPassword;
358     }
359 
360     public String getScmUsername()
361     {
362         return scmUsername;
363     }
364 
365     public void setScmUsername( String scmUsername )
366     {
367         this.scmUsername = scmUsername;
368     }
369 
370     public Collection getProjectGroups()
371     {
372         return projectGroups;
373     }
374 
375     public String getProjectGroupName()
376     {
377         return projectGroupName;
378     }
379 
380     public void setProjectGroupName( String projectGroupName )
381     {
382         this.projectGroupName = projectGroupName;
383     }
384 
385     public int getSelectedProjectGroup()
386     {
387         return selectedProjectGroup;
388     }
389 
390     public void setSelectedProjectGroup( int selectedProjectGroup )
391     {
392         this.selectedProjectGroup = selectedProjectGroup;
393     }
394 
395     public boolean isDisableGroupSelection()
396     {
397         return this.disableGroupSelection;
398     }
399 
400     public void setDisableGroupSelection( boolean disableGroupSelection )
401     {
402         this.disableGroupSelection = disableGroupSelection;
403     }
404 
405     public boolean isScmUseCache()
406     {
407         return scmUseCache;
408     }
409 
410     public void setScmUseCache( boolean scmUseCache )
411     {
412         this.scmUseCache = scmUseCache;
413     }
414 
415     public int getProjectGroupId()
416     {
417         return projectGroupId;
418     }
419 
420     public void setProjectGroupId( int projectGroupId )
421     {
422         this.projectGroupId = projectGroupId;
423     }
424 
425     public List<BuildDefinitionTemplate> getBuildDefinitionTemplates()
426     {
427         return buildDefinitionTemplates;
428     }
429 
430     public void setBuildDefinitionTemplates( List<BuildDefinitionTemplate> buildDefinitionTemplates )
431     {
432         this.buildDefinitionTemplates = buildDefinitionTemplates;
433     }
434 
435     public int getBuildDefinitionTemplateId()
436     {
437         return buildDefinitionTemplateId;
438     }
439 
440     public void setBuildDefinitionTemplateId( int buildDefinitionTemplateId )
441     {
442         this.buildDefinitionTemplateId = buildDefinitionTemplateId;
443     }
444 
445     private boolean isAuthorizedToAddProjectToGroup( String projectGroupName )
446     {
447         try
448         {
449             checkAddProjectToGroupAuthorization( projectGroupName );
450             return true;
451         }
452         catch ( AuthorizationRequiredException authzE )
453         {
454             return false;
455         }
456     }
457 
458     public List<String> getErrorMessages()
459     {
460         return errorMessages;
461     }
462 
463     public void setErrorMessages( List<String> errorMessages )
464     {
465         this.errorMessages = errorMessages;
466     }
467 
468     public void setServletRequest( HttpServletRequest httpServletRequest )
469     {
470         this.httpServletRequest = httpServletRequest;
471     }
472 }