1
2
3
4
5
6
7
8
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 }