blob: 5b9eeeb46725550b09030d4e32c309047a96b509 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.net.www;
27
28import java.net.URL;
29import java.net.ContentHandler;
30import java.util.*;
31import java.io.InputStream;
32import java.io.OutputStream;
33import java.io.BufferedInputStream;
34import java.net.UnknownServiceException;
35
36/**
37 * A class to represent an active connection to an object
38 * represented by a URL.
39 * @author James Gosling
40 */
41
42abstract public class URLConnection extends java.net.URLConnection {
43
44 /** The URL that it is connected to */
45
46 private String contentType;
47 private int contentLength = -1;
48
49 protected MessageHeader properties;
50
51 /** Create a URLConnection object. These should not be created directly:
52 instead they should be created by protocol handers in response to
53 URL.openConnection.
54 @param u The URL that this connects to.
55 */
56 public URLConnection (URL u) {
57 super(u);
58 properties = new MessageHeader();
59 }
60
61 /** Call this routine to get the property list for this object.
62 * Properties (like content-type) that have explicit getXX() methods
63 * associated with them should be accessed using those methods. */
64 public MessageHeader getProperties() {
65 return properties;
66 }
67
68 /** Call this routine to set the property list for this object. */
69 public void setProperties(MessageHeader properties) {
70 this.properties = properties;
71 }
72
73 public void setRequestProperty(String key, String value) {
74 if(connected)
75 throw new IllegalAccessError("Already connected");
76 if (key == null)
77 throw new NullPointerException ("key cannot be null");
78 properties.set(key, value);
79 }
80
81 /**
82 * The following three methods addRequestProperty, getRequestProperty,
83 * and getRequestProperties were copied from the superclass implementation
84 * before it was changed by CR:6230836, to maintain backward compatibility.
85 */
86 public void addRequestProperty(String key, String value) {
87 if (connected)
88 throw new IllegalStateException("Already connected");
89 if (key == null)
90 throw new NullPointerException ("key is null");
91 }
92
93 public String getRequestProperty(String key) {
94 if (connected)
95 throw new IllegalStateException("Already connected");
96 return null;
97 }
98
99 public Map<String,List<String>> getRequestProperties() {
100 if (connected)
101 throw new IllegalStateException("Already connected");
102 return Collections.EMPTY_MAP;
103 }
104
105 public String getHeaderField(String name) {
106 try {
107 getInputStream();
108 } catch (Exception e) {
109 return null;
110 }
111 return properties == null ? null : properties.findValue(name);
112 }
113
114 /**
115 * Return the key for the nth header field. Returns null if
116 * there are fewer than n fields. This can be used to iterate
117 * through all the headers in the message.
118 */
119 public String getHeaderFieldKey(int n) {
120 try {
121 getInputStream();
122 } catch (Exception e) {
123 return null;
124 }
125 MessageHeader props = properties;
126 return props == null ? null : props.getKey(n);
127 }
128
129 /**
130 * Return the value for the nth header field. Returns null if
131 * there are fewer than n fields. This can be used in conjunction
132 * with getHeaderFieldKey to iterate through all the headers in the message.
133 */
134 public String getHeaderField(int n) {
135 try {
136 getInputStream();
137 } catch (Exception e) {
138 return null;
139 }
140 MessageHeader props = properties;
141 return props == null ? null : props.getValue(n);
142 }
143
144 /** Call this routine to get the content-type associated with this
145 * object.
146 */
147 public String getContentType() {
148 if (contentType == null)
149 contentType = getHeaderField("content-type");
150 if (contentType == null) {
151 String ct = null;
152 try {
153 ct = guessContentTypeFromStream(getInputStream());
154 } catch(java.io.IOException e) {
155 }
156 String ce = properties.findValue("content-encoding");
157 if (ct == null) {
158 ct = properties.findValue("content-type");
159
160 if (ct == null)
161 if (url.getFile().endsWith("/"))
162 ct = "text/html";
163 else
164 ct = guessContentTypeFromName(url.getFile());
165 }
166
167 /*
168 * If the Mime header had a Content-encoding field and its value
169 * was not one of the values that essentially indicate no
170 * encoding, we force the content type to be unknown. This will
171 * cause a save dialog to be presented to the user. It is not
172 * ideal but is better than what we were previously doing, namely
173 * bringing up an image tool for compressed tar files.
174 */
175
176 if (ct == null || ce != null &&
177 !(ce.equalsIgnoreCase("7bit")
178 || ce.equalsIgnoreCase("8bit")
179 || ce.equalsIgnoreCase("binary")))
180 ct = "content/unknown";
181 setContentType(ct);
182 }
183 return contentType;
184 }
185
186 /**
187 * Set the content type of this URL to a specific value.
188 * @param type The content type to use. One of the
189 * content_* static variables in this
190 * class should be used.
191 * eg. setType(URL.content_html);
192 */
193 public void setContentType(String type) {
194 contentType = type;
195 properties.set("content-type", type);
196 }
197
198 /** Call this routine to get the content-length associated with this
199 * object.
200 */
201 public int getContentLength() {
202 try {
203 getInputStream();
204 } catch (Exception e) {
205 return -1;
206 }
207 int l = contentLength;
208 if (l < 0) {
209 try {
210 l = Integer.parseInt(properties.findValue("content-length"));
211 setContentLength(l);
212 } catch(Exception e) {
213 }
214 }
215 return l;
216 }
217
218 /** Call this routine to set the content-length associated with this
219 * object.
220 */
221 protected void setContentLength(int length) {
222 contentLength = length;
223 properties.set("content-length", String.valueOf(length));
224 }
225
226 /**
227 * Returns true if the data associated with this URL can be cached.
228 */
229 public boolean canCache() {
230 return url.getFile().indexOf('?') < 0 /* && url.postData == null
231 REMIND */ ;
232 }
233
234 /**
235 * Call this to close the connection and flush any remaining data.
236 * Overriders must remember to call super.close()
237 */
238 public void close() {
239 url = null;
240 }
241}