source: branches/0.19.x/abcl/src/org/armedbear/lisp/util/HttpHead.java

Last change on this file was 12504, checked in by Mark Evenson, 15 years ago

Implement HTTP HEAD Last-Modified checking for ZipCache? objects.

Since it seems that no Sun-derived JVM ever invalidates its cache of
URLConnection objects, we have to check for modification "manually".
This implementation is "better than nothing", but not expected to be
especially robust. Most notably, this implementation does not attempt
to use http proxies if they have been specified to the JVM by the
'http.proxy' system property.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.6 KB
Line 
1/*
2 * HttpHead.java
3 *
4 * Copyright (C) 2010 Mark Evenson
5 * $Id: HttpHead.java 12504 2010-02-23 14:34:45Z mevenson $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33package org.armedbear.lisp.util;
34
35import org.armedbear.lisp.Debug;
36
37import java.io.BufferedReader;
38import java.io.IOException;
39import java.io.InputStreamReader;
40import java.io.PrintWriter;
41import java.net.InetSocketAddress;
42import java.net.MalformedURLException;
43import java.net.Proxy;
44import java.net.Socket;
45import java.net.URL;
46
47/**
48 * Use HTTP/1.1 HEAD to retrieve the specified header field.
49 */
50public class HttpHead {
51    static private String get(String urlString, String key) {
52        URL url = null;
53        try {
54            url = new URL(urlString);
55        } catch (MalformedURLException e) {
56            log("Failed to form url from " + "'" + urlString + "'" + ": " + e);
57        }
58        return get(url, key);
59    }
60
61    static public String get(URL url, String key) {
62        Socket socket = null;
63        String result = null;
64        try {
65            String protocol = url.getProtocol();
66            if (!protocol.equals("http")) {
67                log("The protocol " + "'" + protocol + "'" + " is not http.");
68                return result;
69            }
70
71            socket = new Socket(Proxy.NO_PROXY); // XXX add Proxy
72
73            int port = url.getPort();
74            if (port == -1) {
75                port = 80;
76            }
77            InetSocketAddress address = new InetSocketAddress(url.getHost(), port);
78            try {
79                socket.connect(address, 5000); // ??? too long?  too short?
80            } catch (IOException ex) {
81                log("Connection failed: " + ex);
82                return result;
83            }
84
85            PrintWriter out = null;
86            BufferedReader in = null;
87            try {
88                out = new PrintWriter(socket.getOutputStream());
89                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
90            } catch (IOException e) {
91                log("Failed to establish socket io: " + e);
92                return result;
93            }
94
95            String path = url.getPath();
96            out.println("HEAD " + url + " HTTP/1.1");
97            out.println("Connection: close");
98            out.println("");
99            out.flush();
100
101            String line = null;
102            try {
103                line = in.readLine();
104            } catch (IOException e) {
105                log("Failed to read HTTP response: " + e);
106            }
107            String status[] = line.split("\\s");
108            if (status[1].equals("200")) {
109                result = findHeader(in, key);
110            } else if (status[1].startsWith("3")) {
111                // Follow redirects ad nauseum
112                String location = findHeader(in, "Location");
113                if (location != null) {
114                    return get(location, key);
115                }
116            } else {
117                log("Unexpected response: " + line);
118            }
119        } finally {
120            try {
121                socket.close();
122            } catch (IOException e) {
123            }
124        }
125        return result;
126    }
127
128    static private String findHeader(BufferedReader in, String key) {
129        String result = null;
130        String line;
131        try {
132            while ((line = in.readLine()) != null) {
133                int i = line.indexOf(":");
134                if (i == -1) {
135                    continue; // XXX parse multi-line HTTP headers
136                }
137                String k = line.substring(0, i);
138                String v = line.substring(i + 1).trim();
139                if (k.equals(key)) {
140                    result = v;
141                    break;
142                }
143            }
144        } catch (IOException e) {
145            log("Failed to read headers: " + e);
146        }
147        return result;
148    }
149
150    static private void log(String message) {
151        Debug.warn(message);
152    }
153
154    public static void main(String argv[]) {
155        if (argv.length != 1) {
156            System.out.println("Usage: <cmd> URL");
157            return;
158        }
159        String modified = get(argv[0], "Last-Modified");
160        if (modified != null) {
161            System.out.println("Last-Modified: " + modified);
162        } else {
163            System.out.println("No result returned.");
164        }
165    }
166}
Note: See TracBrowser for help on using the repository browser.