001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.console.databasemanager.wizard;
018
019 import java.io.BufferedOutputStream;
020 import java.io.File;
021 import java.io.FileOutputStream;
022 import java.io.IOException;
023 import java.io.InputStream;
024 import java.io.OutputStream;
025 import java.io.Serializable;
026 import java.net.MalformedURLException;
027 import java.net.URL;
028 import java.net.URLConnection;
029 import java.util.ArrayList;
030 import java.util.Collections;
031 import java.util.HashSet;
032 import java.util.Iterator;
033 import java.util.List;
034 import java.util.Properties;
035 import java.util.Random;
036 import java.util.Set;
037 import java.util.jar.JarEntry;
038 import java.util.jar.JarFile;
039 import org.apache.commons.logging.Log;
040 import org.apache.commons.logging.LogFactory;
041 import org.apache.geronimo.kernel.repository.Artifact;
042 import org.apache.geronimo.kernel.repository.FileWriteMonitor;
043 import org.apache.geronimo.kernel.repository.WriteableRepository;
044
045 /**
046 * A utility that handles listing and downloading available JDBC driver JARs.
047 * It can handle straight JARs and also JARs in ZIP files.
048 *
049 * @version $Rev: 476061 $ $Date: 2006-11-17 01:36:50 -0500 (Fri, 17 Nov 2006) $
050 */
051 public class DriverDownloader {
052 private final static Log log = LogFactory.getLog(DriverDownloader.class);
053 Random random;
054
055 public Properties readDriverFile(URL url) {
056 try {
057 InputStream in = url.openStream();
058 Properties props = new Properties();
059 props.load(in);
060 in.close();
061 return props;
062 } catch (IOException e) {
063 log.error("Unable to download driver properties", e);
064 return null;
065 }
066 }
067
068 public DriverInfo[] loadDriverInfo(URL driverInfoFile) {
069 List list = new ArrayList();
070 Properties props = readDriverFile(driverInfoFile);
071 if(props == null) {
072 return new DriverInfo[0];
073 }
074 Set drivers = new HashSet();
075 for (Iterator it = props.keySet().iterator(); it.hasNext();) {
076 String key = (String) it.next();
077 if(!key.startsWith("driver.")) {
078 continue;
079 }
080 int pos = key.indexOf('.', 7);
081 if(pos > -1) {
082 drivers.add(key.substring(7, pos));
083 }
084 }
085 List urls = new ArrayList();
086 for (Iterator it = drivers.iterator(); it.hasNext();) {
087 String driver = (String) it.next();
088 String name = props.getProperty("driver."+driver+".name");
089 String repository = props.getProperty("driver."+driver+".repository");
090 String unzip = props.getProperty("driver."+driver+".unzip");
091 urls.clear();
092 int index = 1;
093 while(true) {
094 String url = props.getProperty("driver."+driver+".url."+index);
095 if(url != null) {
096 ++index;
097 try {
098 urls.add(new URL(url));
099 } catch (MalformedURLException e) {
100 log.error("Unable to process URL from driver list", e);
101 }
102 } else {
103 break;
104 }
105 }
106 if(name != null && repository != null && urls.size() > 0) {
107 DriverInfo info = new DriverInfo(name, repository);
108 info.setUnzipPath(unzip);
109 info.setUrls((URL[]) urls.toArray(new URL[urls.size()]));
110 list.add(info);
111 }
112 }
113 Collections.sort(list);
114 return (DriverInfo[]) list.toArray(new DriverInfo[list.size()]);
115 }
116
117 /**
118 * Downloads a driver and loads it into the local repository.
119 */
120 public void loadDriver(WriteableRepository repo, DriverInfo driver, FileWriteMonitor monitor) throws IOException {
121 int urlIndex = 0;
122 if (driver.urls.length > 1) {
123 if (random == null) {
124 random = new Random();
125 }
126 urlIndex = random.nextInt(driver.urls.length);
127 }
128 URL url = driver.urls[urlIndex];
129 InputStream in;
130 String uri = driver.getRepositoryURI();
131 if (driver.unzipPath != null) {
132 byte[] buf = new byte[1024];
133 int size;
134 int total = 0;
135 int threshold = 10240;
136 URLConnection uc = url.openConnection();
137 int filesize = uc.getContentLength();
138 InputStream net = uc.getInputStream();
139 JarFile jar = null;
140 File download = null;
141 try {
142 download = File.createTempFile("geronimo-driver-download", ".zip");
143 OutputStream out = new BufferedOutputStream(new FileOutputStream(download));
144 if (monitor != null) {
145 monitor.writeStarted("Download driver archive to " + download, filesize);
146 }
147 try {
148 while ((size = net.read(buf)) > -1) {
149 out.write(buf, 0, size);
150 if (monitor != null) {
151 total += size;
152 if (total > threshold) {
153 monitor.writeProgress(total);
154 threshold += 10240;
155 }
156 }
157 }
158 out.flush();
159 out.close();
160 } finally {
161 if (monitor != null) {
162 monitor.writeComplete(total);
163 }
164 }
165 jar = new JarFile(download);
166 JarEntry entry = jar.getJarEntry(driver.unzipPath);
167 if (entry == null) {
168 log.error("Cannot extract driver JAR " + driver.unzipPath + " from download file " + url);
169 } else {
170 in = jar.getInputStream(entry);
171 repo.copyToRepository(in, (int)entry.getSize(), Artifact.create(uri), monitor);
172 }
173 } finally {
174 if (jar != null) try {
175 jar.close();
176 } catch (IOException e) {
177 log.error("Unable to close JAR file", e);
178 }
179 if (download != null) {
180 download.delete();
181 }
182 }
183 } else {
184 URLConnection con = url.openConnection();
185 in = con.getInputStream();
186 repo.copyToRepository(in, con.getContentLength(), Artifact.create(uri), monitor);
187 }
188 }
189
190 public static class DriverInfo implements Comparable, Serializable {
191 private final static long serialVersionUID = -1202452382992975449L;
192
193 private String name;
194 private String repositoryURI;
195 private String unzipPath;
196 private URL[] urls;
197
198 public DriverInfo(String name, String repositoryURI) {
199 this.name = name;
200 this.repositoryURI = repositoryURI;
201 }
202
203 public String getName() {
204 return name;
205 }
206
207 public void setName(String name) {
208 this.name = name;
209 }
210
211 public String getRepositoryURI() {
212 return repositoryURI;
213 }
214
215 public void setRepositoryURI(String repositoryURI) {
216 this.repositoryURI = repositoryURI;
217 }
218
219 public String getUnzipPath() {
220 return unzipPath;
221 }
222
223 public void setUnzipPath(String unzipPath) {
224 this.unzipPath = unzipPath;
225 }
226
227 public URL[] getUrls() {
228 return urls;
229 }
230
231 public void setUrls(URL[] urls) {
232 this.urls = urls;
233 }
234
235 public int compareTo(Object o) {
236 return name.compareTo(((DriverInfo)o).name);
237 }
238 }
239 }