View Javadoc

1   /*
2    * $Id
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.modules.boot;
12  
13  import org.mule.util.ClassUtils;
14  import org.mule.util.FileUtils;
15  import org.mule.util.NumberUtils;
16  import org.mule.util.StringUtils;
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.net.URL;
21  import java.net.UnknownHostException;
22  import java.util.ArrayList;
23  import java.util.Enumeration;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Properties;
27  
28  import org.apache.commons.httpclient.ConnectTimeoutException;
29  import org.apache.commons.httpclient.HostConfiguration;
30  import org.apache.commons.httpclient.HttpClient;
31  import org.apache.commons.httpclient.HttpMethod;
32  import org.apache.commons.httpclient.HttpState;
33  import org.apache.commons.httpclient.HttpStatus;
34  import org.apache.commons.httpclient.UsernamePasswordCredentials;
35  import org.apache.commons.httpclient.auth.AuthScope;
36  import org.apache.commons.httpclient.methods.GetMethod;
37  import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
38  
39  public class LibraryDownloader
40  {
41      private static final int HTTP_CONNECTION_TIMEOUT = 10000;
42      private static final String REPO_CENTRAL = "http://repo1.maven.org/maven2";
43      private static final String BOOTSTRAP_LIBRARY_DOWNLOAD_DESCRIPTION_PREFIX = "mule.bootstrap.library.download.description.";
44  
45      private static final String PROXY_ERROR_MESSAGE = "Unable to reach remote repository. This is most likely because you are behind a firewall and missing proxy settings in Mule."
46          + "Proxy options can be passed during startup as follows:\n"
47          + " -M-Dhttp.proxyHost=YOUR_HOST\n"
48          + " -M-Dhttp.proxyPort=YOUR_PORT\n"
49          + " -M-Dhttp.proxyUsername=YOUR_USERNAME\n"
50          + " -M-Dhttp.proxyPassword=YOUR_PASSWORD\n";
51      
52      private MuleBootstrapUtils.ProxyInfo proxyInfo;
53      private HostConfiguration hostConfig;
54      private HttpState httpState;
55  
56      private File muleHome;
57      private File mavenRepo = null;
58      private HttpClient client;
59      
60      private List libraryDownloadDescriptions = new ArrayList();
61  
62      public LibraryDownloader(File muleHome)
63      {
64          this(muleHome, new MuleBootstrapUtils.ProxyInfo(
65              System.getProperty("http.proxyHost"), 
66              System.getProperty("http.proxyPort"), 
67              System.getProperty("http.proxyUsername"), 
68              System.getProperty("http.proxyPassword")));
69      }
70      
71      public LibraryDownloader(File muleHome, String proxyHost, String proxyPort, String proxyUsername, String proxyPassword)
72      {
73          this(muleHome, new MuleBootstrapUtils.ProxyInfo(proxyHost, proxyPort, proxyUsername, proxyPassword));
74      }
75      
76      public LibraryDownloader(File muleHome, MuleBootstrapUtils.ProxyInfo proxyInfo)
77      {
78          this.muleHome = muleHome;
79          this.proxyInfo = proxyInfo;
80  
81          configureMavenRepository();
82          configureHttpClient();
83          configureHttpProxy();
84          
85          readLibraryDownloadDescriptions();
86      }
87      
88      public List downloadLibraries() throws IOException
89      {
90          List libraryUrls = new ArrayList();
91          Exception proxyException = null;
92          try
93          {
94              Iterator iter = libraryDownloadDescriptions.iterator();
95              while (iter.hasNext())
96              {
97                  URL libraryUrl = downloadLibrary((Library) iter.next());
98                  if (libraryUrl != null)
99                  {
100                     libraryUrls.add(libraryUrl);
101                 }
102             }
103         }
104         catch (UnknownHostException uhe)
105         {
106             proxyException = uhe;
107         }
108         catch (ConnectTimeoutException cte)
109         {
110             proxyException = cte;
111         }
112         finally
113         {
114             if (proxyException != null)
115             {
116                 System.err.println();
117                 IOException ex = new IOException(PROXY_ERROR_MESSAGE);
118                 ex.initCause(proxyException);
119                 throw ex;
120             }
121         }
122         return libraryUrls;        
123     }
124     
125     private void configureMavenRepository()
126     {
127         String mavenRepoVar = System.getProperty("m2.repo");
128         if (!StringUtils.isBlank(mavenRepoVar))
129         {
130             mavenRepo = new File(mavenRepoVar).getAbsoluteFile();
131             if (!mavenRepo.exists() || !mavenRepo.isDirectory())
132             {
133                 mavenRepo = null;
134             }
135         }
136     }
137 
138     private void configureHttpClient()
139     {
140         client = new HttpClient();
141         HttpConnectionManagerParams connParams = new HttpConnectionManagerParams();
142         connParams.setConnectionTimeout(HTTP_CONNECTION_TIMEOUT);
143         client.getHttpConnectionManager().setParams(connParams);
144     }
145     
146     private void configureHttpProxy()
147     {
148         hostConfig = new HostConfiguration();
149         if (StringUtils.isNotBlank(proxyInfo.host))
150         {
151             hostConfig.setProxy(proxyInfo.host, NumberUtils.toInt(proxyInfo.port));
152         }
153         httpState = new HttpState();
154         if (StringUtils.isNotBlank(proxyInfo.username))
155         {
156             httpState.setProxyCredentials(new AuthScope(null, -1, null, null),
157                 new UsernamePasswordCredentials(proxyInfo.username, proxyInfo.password));
158         }
159     }
160     
161     private void readLibraryDownloadDescriptions()
162     {
163         Properties properties = System.getProperties();
164         Enumeration keys = properties.keys();
165         
166         while (keys.hasMoreElements())
167         {
168             String key = (String) keys.nextElement();
169             if (key.startsWith(BOOTSTRAP_LIBRARY_DOWNLOAD_DESCRIPTION_PREFIX))
170             {
171                 String[] descriptions = properties.getProperty(key).split(",");
172                 if (descriptions != null && descriptions.length == 3)
173                 {
174                     libraryDownloadDescriptions.add(new Library(descriptions[0].trim(), descriptions[1].trim(), descriptions[2].trim()));
175                 }
176             }
177         }
178     }
179     
180     private URL downloadLibrary(Library library) throws IOException
181     {
182         URL libraryUrl = null;
183         if (! ClassUtils.isClassOnPath(library.testClassName, MuleBootstrapUtils.class))
184         {
185             libraryUrl = downloadLibraryFromLocalRepository(library.jarPath, library.jarName);
186             if (libraryUrl == null)
187             {
188                 libraryUrl = downloadLibraryFromRemoteRepository(library.jarPath, library.jarName);
189             }            
190         }
191         return libraryUrl;
192     }
193 
194     private URL downloadLibraryFromLocalRepository(String path, String destinationFileName) throws IOException
195     {
196         URL libraryUrl = null;
197         if (mavenRepo != null)
198         {
199             File sourceFile = new File(mavenRepo, path + File.separator + destinationFileName).getCanonicalFile();
200             if (sourceFile.exists())
201             {
202                 System.out.print("Copying from local repository " + sourceFile.getAbsolutePath() + " ...");
203                 File destinationFile = new File(new File(muleHome, DefaultMuleClassPathConfig.USER_DIR).getCanonicalFile(), destinationFileName).getCanonicalFile();
204                 FileUtils.copyFile(sourceFile, destinationFile);
205                 System.out.println("done");
206                 libraryUrl = destinationFile.toURL();
207             }
208         }
209         return libraryUrl;
210     }
211 
212     private URL downloadLibraryFromRemoteRepository(String path, String destinationFileName) throws IOException
213     {
214         URL libraryUrl = null;
215         HttpMethod httpMethod = new GetMethod(REPO_CENTRAL + path + '/' + destinationFileName);
216         try
217         {
218             System.out.print("Downloading " + httpMethod.getURI() + " ...");
219             client.executeMethod(hostConfig, httpMethod, httpState);
220             if (httpMethod.getStatusCode() == HttpStatus.SC_OK)
221             {
222                 File destinationFile = new File(new File(muleHome, DefaultMuleClassPathConfig.USER_DIR), destinationFileName);
223                 FileUtils.copyStreamToFile(httpMethod.getResponseBodyAsStream(), destinationFile);
224                 System.out.println("done");
225                 libraryUrl = destinationFile.toURL();
226             }
227             else
228             {
229                 System.out.println();
230                 throw new IOException("HTTP request failed: " + httpMethod.getStatusLine().toString());
231             }
232         }
233         finally
234         {
235             httpMethod.releaseConnection();
236         }
237         return libraryUrl;
238     }
239     
240     private static class Library
241     {
242         public String testClassName;
243         public String jarPath;
244         public String jarName;
245         
246         public Library(String testClassName, String jarPath, String jarName)
247         {
248             this.testClassName = testClassName;
249             this.jarPath = jarPath;
250             this.jarName = jarName;
251         }
252     }
253 }