View Javadoc

1   package org.apache.maven.continuum.project.builder;
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.FileNotFoundException;
24  import java.io.FileWriter;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.net.MalformedURLException;
28  import java.net.URI;
29  import java.net.URISyntaxException;
30  import java.net.URL;
31  import java.net.UnknownHostException;
32  
33  import org.apache.commons.io.IOUtils;
34  import org.apache.http.HttpException;
35  import org.apache.http.HttpResponse;
36  import org.apache.http.HttpVersion;
37  import org.apache.http.auth.AuthScope;
38  import org.apache.http.auth.UsernamePasswordCredentials;
39  import org.apache.http.client.methods.HttpGet;
40  import org.apache.http.conn.ClientConnectionManager;
41  import org.apache.http.conn.params.ConnManagerPNames;
42  import org.apache.http.conn.params.ConnPerRouteBean;
43  import org.apache.http.conn.scheme.PlainSocketFactory;
44  import org.apache.http.conn.scheme.Scheme;
45  import org.apache.http.conn.scheme.SchemeRegistry;
46  import org.apache.http.impl.client.DefaultHttpClient;
47  import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
48  import org.apache.http.params.BasicHttpParams;
49  import org.apache.http.params.HttpParams;
50  import org.apache.http.params.HttpProtocolParams;
51  import org.apache.http.util.EntityUtils;
52  import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
53  import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
54  import org.codehaus.plexus.util.FileUtils;
55  import org.codehaus.plexus.util.IOUtil;
56  import org.codehaus.plexus.util.StringUtils;
57  import org.slf4j.Logger;
58  import org.slf4j.LoggerFactory;
59  
60  
61  /**
62   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
63   * @version $Id: AbstractContinuumProjectBuilder.java 800613 2009-08-03 23:16:13Z ctan $
64   */
65  public abstract class AbstractContinuumProjectBuilder
66      implements ContinuumProjectBuilder, Initializable
67  {
68      private static final String TMP_DIR = System.getProperty( "java.io.tmpdir" );
69  
70      protected final Logger log = LoggerFactory.getLogger( getClass() );
71  
72      private DefaultHttpClient httpClient;
73  
74      public void initialize()
75          throws InitializationException
76      {
77          SchemeRegistry schemeRegistry = new SchemeRegistry();
78          // http scheme
79          schemeRegistry.register( new Scheme( "http", PlainSocketFactory.getSocketFactory(), 80 ) );
80          // https scheme
81          schemeRegistry.register( new Scheme( "https", new EasySSLSocketFactory(), 443 ) );
82  
83          HttpParams params = new BasicHttpParams();
84          // TODO put this values to a configuration way ???
85          params.setParameter( ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30 );
86          params.setParameter( ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean( 30 ) );
87          HttpProtocolParams.setVersion( params, HttpVersion.HTTP_1_1 );
88  
89          ClientConnectionManager cm = new ThreadSafeClientConnManager( params, schemeRegistry );
90  
91          httpClient = new DefaultHttpClient( cm, params );
92      }
93  
94      protected File createMetadataFile( URL metadata, String username, String password,
95                                         ContinuumProjectBuildingResult result )
96          throws IOException, URISyntaxException, HttpException
97      {
98          String url = metadata.toExternalForm();
99          if ( metadata.getProtocol().startsWith( "http" ) )
100         {
101             url = hidePasswordInUrl( url );
102         }
103         log.info( "Downloading " + url );
104 
105         InputStream is;
106 
107         if ( metadata.getProtocol().startsWith( "http" ) )
108         {
109             URI uri = metadata.toURI();
110             HttpGet httpGet = new HttpGet( uri );
111 
112             httpClient.getCredentialsProvider().clear();
113 
114             // basic auth
115             if ( username != null && password != null )
116             {
117                 httpClient.getCredentialsProvider().setCredentials( new AuthScope( uri.getHost(), uri.getPort() ),
118                                                                     new UsernamePasswordCredentials( username,
119                                                                                                      password ) );
120             }
121 
122             HttpResponse httpResponse = httpClient.execute( httpGet );
123 
124             // basic auth 
125 
126             int res = httpResponse.getStatusLine().getStatusCode();
127             switch ( res )
128             {
129                 case 200:
130                     break;
131                 case 401:
132                     log.error( "Error adding project: Unauthorized " + url );
133                     result.addError( ContinuumProjectBuildingResult.ERROR_UNAUTHORIZED );
134                     return null;
135                 default:
136                     log.warn( "skip non handled http return code " + res );
137             }
138             is = IOUtils.toInputStream( EntityUtils.toString( httpResponse.getEntity(), EntityUtils.getContentCharSet(
139                 httpResponse.getEntity() ) ) );
140         }
141         else
142         {
143             is = metadata.openStream();
144         }
145 
146         String path = metadata.getPath();
147 
148         String baseDirectory;
149 
150         String fileName;
151 
152         int lastIndex = path.lastIndexOf( "/" );
153 
154         if ( lastIndex >= 0 )
155         {
156             baseDirectory = path.substring( 0, lastIndex );
157 
158             // Required for windows
159             int colonIndex = baseDirectory.indexOf( ":" );
160 
161             if ( colonIndex >= 0 )
162             {
163                 baseDirectory = baseDirectory.substring( colonIndex + 1 );
164             }
165 
166             fileName = path.substring( lastIndex + 1 );
167         }
168         else
169         {
170             baseDirectory = "";
171 
172             fileName = path;
173         }
174 
175         // Little hack for URLs that contains '*' like "http://svn.codehaus.org/*checkout*/trunk/pom.xml?root=plexus"
176         baseDirectory = StringUtils.replace( baseDirectory, "*", "" );
177 
178         File continuumTmpDir = new File( TMP_DIR, "continuum" );
179 
180         // FIXME should deleted after has been reading
181         File uploadDirectory = new File( continuumTmpDir, baseDirectory );
182 
183         uploadDirectory.deleteOnExit();
184 
185         // resolve any '..' as it will cause issues
186         uploadDirectory = uploadDirectory.getCanonicalFile();
187 
188         uploadDirectory.mkdirs();
189 
190         FileUtils.forceDeleteOnExit( continuumTmpDir );
191 
192         File file = new File( uploadDirectory, fileName );
193 
194         file.deleteOnExit();
195 
196         FileWriter writer = new FileWriter( file );
197 
198         IOUtil.copy( is, writer );
199 
200         is.close();
201 
202         writer.close();
203 
204         return file;
205     }
206 
207     private String hidePasswordInUrl( String url )
208     {
209         int indexAt = url.indexOf( "@" );
210 
211         if ( indexAt < 0 )
212         {
213             return url;
214         }
215 
216         String s = url.substring( 0, indexAt );
217 
218         int pos = s.lastIndexOf( ":" );
219 
220         return s.substring( 0, pos + 1 ) + "*****" + url.substring( indexAt );
221     }
222 
223     /**
224      * Create metadata file and handle exceptions, adding the errors to the result object.
225      *
226      * @param result   holder with result and errors.
227      * @param metadata
228      * @param username
229      * @param password
230      * @return
231      */
232     protected File createMetadataFile( ContinuumProjectBuildingResult result, URL metadata, String username,
233                                        String password )
234     {
235         String url = metadata.toExternalForm();
236 
237         if ( metadata.getProtocol().startsWith( "http" ) )
238         {
239             url = hidePasswordInUrl( url );
240         }
241 
242         try
243         {
244             return createMetadataFile( metadata, username, password, result );
245         }
246         catch ( FileNotFoundException e )
247         {
248             log.info( "URL not found: " + url, e );
249             result.addError( ContinuumProjectBuildingResult.ERROR_POM_NOT_FOUND );
250         }
251         catch ( MalformedURLException e )
252         {
253             log.info( "Malformed URL: " + url, e );
254             result.addError( ContinuumProjectBuildingResult.ERROR_MALFORMED_URL );
255         }
256         catch ( URISyntaxException e )
257         {
258             log.info( "Malformed URL: " + url, e );
259             result.addError( ContinuumProjectBuildingResult.ERROR_MALFORMED_URL );
260         }
261         catch ( UnknownHostException e )
262         {
263             log.info( "Unknown host: " + url, e );
264             result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN_HOST );
265         }
266         catch ( IOException e )
267         {
268             log.warn( "Could not download the URL: " + url, e );
269             result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN );
270         }
271         catch ( HttpException e )
272         {
273             log.warn( "Could not download the URL: " + url, e );
274             result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN );
275         }
276         return null;
277     }
278 
279 }