KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > inversoft > savant > InternetProcess


1 /*
2  * Copyright (c) 2003-2004, Inversoft, All Rights Reserved
3  *
4  * This software is distribuable under the GNU Lesser General Public License.
5  * For more information visit gnu.org.
6  */

7 package com.inversoft.savant;
8
9
10 import java.io.BufferedReader JavaDoc;
11 import java.io.File JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.io.InputStream JavaDoc;
14 import java.io.InputStreamReader JavaDoc;
15 import java.net.HttpURLConnection JavaDoc;
16 import java.net.MalformedURLException JavaDoc;
17 import java.net.URL JavaDoc;
18 import java.net.URLConnection JavaDoc;
19
20 import com.inversoft.savant.log.Log;
21
22
23 /**
24  * <p>
25  * This class is the base class of Internet download processors.
26  * </p>
27  *
28  * @author Brian Pontarelli
29  */

30 public abstract class InternetProcess implements Process JavaDoc {
31
32     private String JavaDoc defaultDomain;
33     private File JavaDoc mapping;
34     private boolean failonmd5;
35
36
37     public String JavaDoc getDefaultdomain() {
38         return defaultDomain;
39     }
40
41     public void setDefaultdomain(String JavaDoc defaultDomain) {
42         this.defaultDomain = defaultDomain;
43     }
44
45     public String JavaDoc getUrl() {
46         return defaultDomain;
47     }
48
49     public void setUrl(String JavaDoc defaultDomain) {
50         this.defaultDomain = defaultDomain;
51     }
52
53     public File JavaDoc getMapping() {
54         return mapping;
55     }
56
57     public void setMapping(File JavaDoc mapping) {
58         this.mapping = mapping;
59     }
60
61     public boolean isFailonmd5() {
62         return failonmd5;
63     }
64
65     public void setFailonmd5(boolean failonmd5) {
66         this.failonmd5 = failonmd5;
67     }
68
69     /**
70      * Returns a printable name of this process. Used in error messaging.
71      *
72      * @return The name
73      */

74     public abstract String JavaDoc getProcessName();
75
76     /**
77      * Validates the process. Processes must have either a default domain or a
78      * mapping file.
79      *
80      * @throws SavantException If the process is invalid
81      */

82     public void validate() throws SavantException {
83         if (defaultDomain == null && mapping == null) {
84             throw new SavantException("The " + getProcessName() + " requires " +
85                 "either a default domain or a mapping file");
86         }
87     }
88
89     /**
90      * Using the URL spec given, this method connects to the URL, reads the file
91      * from the URL and stores the file in the local cache store. The artifact is
92      * used to determine the local cache store directory and file name.
93      *
94      * @param builder The URLBuilder to use to generate URLs
95      * @param artifact The artifact being fetched and stored
96      * @param localCache The local cache to store the artifact in
97      * @return The File of the artifact in the local cache
98      */

99     protected File JavaDoc findFile(URLBuilder builder, Artifact artifact,
100             LocalCacheStore localCache)
101     throws SavantException {
102         URL JavaDoc artifactURL = builder.buildURL(defaultDomain, mapping, artifact);
103         if (artifactURL == null) {
104             throw new SavantException("Unable to build URL for artifact [" +
105                 artifact.toString() + "]");
106         }
107
108         URLConnection JavaDoc uc = openConnection(artifactURL);
109         if (uc == null) {
110             return null;
111         }
112
113         InputStream JavaDoc is = null;
114         try {
115             if (!isValid(uc)) {
116                 return null;
117             }
118
119             byte[] md5 = getMD5Hash(builder, artifact);
120             is = uc.getInputStream();
121
122             return localCache.store(artifact, is, md5, failonmd5);
123         } catch (IOException JavaDoc ioe) {
124             Log.log("Unable to download artifact [" + artifact + "]", Log.ERROR);
125             throw new SavantException(ioe);
126         } catch (SavantException se) {
127             Log.log(se.getMessage(), Log.ERROR);
128             throw new SavantException(se);
129         } finally {
130             if (is != null) {
131                 try {
132                     is.close();
133                 } catch (IOException JavaDoc ioe) {
134                     throw new SavantException(ioe);
135                 }
136             }
137         }
138     }
139
140     /**
141      * Builds the MD5 hash using the URLBuilder to build a URL to the MD5 file for
142      * the given artifact.
143      *
144      * @param builder The URLBuilder to call the
145      * {@link URLBuilder#buildMD5URL(String, File, Artifact)} method on.
146      * @param artifact The artifact to build the hash for
147      * @return The hash or null if it doesn't exist
148      * @throws SavantException If the hash could not be read
149      */

150     protected byte[] getMD5Hash(URLBuilder builder, Artifact artifact)
151     throws SavantException {
152         byte[] bytes = null;
153         URL JavaDoc url = builder.buildMD5URL(defaultDomain, mapping, artifact);
154         if (url != null) {
155             URLConnection JavaDoc uc = openConnection(url);
156             if (isValid(uc)) {
157                 StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
158                 try {
159                     InputStream JavaDoc is = uc.getInputStream();
160                     InputStreamReader JavaDoc isr = new InputStreamReader JavaDoc(is);
161                     BufferedReader JavaDoc br = new BufferedReader JavaDoc(isr);
162                     char[] c = new char[1024];
163                     int count;
164                     while ((count = br.read(c, 0, 1024)) != -1) {
165                         for (int i = 0; i < count; i++) {
166                             if (Character.isWhitespace(c[i])) {
167                                 continue;
168                             }
169
170                             buf.append(c[i]);
171                         }
172                     }
173
174                     br.close();
175                     isr.close();
176                     is.close();
177
178                     if (buf.length() > 0) {
179                         bytes = StringTools.fromHex(buf.toString());
180                     }
181                 } catch (IOException JavaDoc ioe) {
182                     Log.log("Unable to download MD5 (skipping) for artifact [" +
183                         artifact + "]", Log.DEBUG);
184                 } catch (IllegalArgumentException JavaDoc iae) {
185                     Log.log("Unable to download MD5 (skipping) for artifact [" +
186                         artifact + "]", Log.DEBUG);
187                 }
188             }
189         }
190
191         return bytes;
192     }
193
194     /**
195      * Updates the given artifact with its dependencies by parsing the XML
196      * dependency file (if one exists).
197      *
198      * @param builder The URLBuilder that will build the URL to the XML file
199      * @param artifact The artifact to update
200      * @param localCache The local cache store to cache the dependency file if
201      * found.
202      * @throws SavantException If building, parsing or content failed or was
203      * invalid
204      */

205     protected boolean resolveArtifactDependencies(URLBuilder builder, Artifact artifact,
206         LocalCacheStore localCache)
207     throws SavantException {
208         URL JavaDoc url = builder.buildDepsURL(defaultDomain, mapping, artifact);
209         if (url != null) {
210             URLConnection JavaDoc uc = openConnection(url);
211             if (isValid(uc)) {
212                 InputStream JavaDoc is = null;
213                 File JavaDoc tmp = null;
214                 try {
215                     is = uc.getInputStream();
216                     tmp = File.createTempFile("savant", "deps");
217
218                     FileTools.output(is, tmp);
219                     ArtifactTools.resolveArtifactDependencies(artifact, tmp);
220                     localCache.storeDeps(artifact, tmp);
221
222                     return true;
223                 } catch (IOException JavaDoc e) {
224                     // Smother, this means the resource doesn't exist
225
Log.log("Unable to locate artifact dependency XML for artifact [" +
226                         artifact + "]", Log.DEBUG);
227                 } finally {
228                     try {
229                         if (is != null) {
230                             is.close();
231                         }
232
233                         if (tmp != null) {
234                             tmp.delete();
235                         }
236                     } catch (IOException JavaDoc ioe) {
237                         throw new SavantException(ioe);
238                     }
239                 }
240             }
241         }
242
243         return false;
244     }
245
246     /**
247      * Opens a HTTP connection to the given URL. If the URL is invalid, a
248      * BuildException is thrown. If the URL can't be opened, this does not error
249      * out, but just returns null.
250      *
251      * @param url The URL to open
252      * @return The connection if if can be opened, null if it can't
253      */

254     protected URLConnection JavaDoc openConnection(URL JavaDoc url) throws SavantException {
255         Log.log("Opening connection to [" + url + "]", Log.DEBUG);
256         URLConnection JavaDoc uc = null;
257         try {
258             uc = url.openConnection();
259             uc.connect();
260         } catch (MalformedURLException JavaDoc mue) {
261             throw new SavantException(mue);
262         } catch (IOException JavaDoc ioe) {
263             // This is okay, because the URL might be unreachable
264
Log.log("Unable to open connection to [" + url + "] because [" +
265                 ioe.getMessage() + "]", Log.INFO);
266         }
267
268         return uc;
269     }
270
271     /**
272      * Verifies that the URL connection is valid by fetching the HTTP header
273      * response code (by first casting to an HttpURLConnection) and ensuring
274      * that it is either accepted or ok. If the URLConnection is not an HTTP
275      * connection, this method returns true.
276      *
277      * @param uc The URL connection validate
278      * @return True if valid, false otherwise
279      * @throws SavantException If the response code could not be fetched
280      */

281     protected boolean isValid(URLConnection JavaDoc uc) throws SavantException {
282         boolean valid = true;
283         if (uc instanceof HttpURLConnection JavaDoc) {
284             try {
285                 int code = ((HttpURLConnection JavaDoc) uc).getResponseCode();
286                 Log.log("Got code from URL of [" + code + "]", Log.DEBUG);
287                 valid = (code == HttpURLConnection.HTTP_ACCEPTED ||
288                         code == HttpURLConnection.HTTP_OK);
289             } catch (IOException JavaDoc ioe) {
290                 Log.log("Unable to verify the status of HTTP connection to the URL [" +
291                     uc.getURL() + "]", Log.ERROR);
292                 throw new SavantException(ioe);
293             }
294         }
295
296         return valid;
297     }
298 }
Popular Tags