OSDN Git Service

12e8a8b4cc66f1750474584f80c427be0d976fbc
[pf3gnuchains/gcc-fork.git] / libjava / java / net / URLConnection.java
1 // URLConnection.java - Superclass of all communications links between
2 //                      an application and a URL.
3
4 /* Copyright (C) 1999  Cygnus Solutions
5
6    This file is part of libgcj.
7
8 This software is copyrighted work licensed under the terms of the
9 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
10 details.  */
11
12 package java.net;
13
14 import java.io.*;
15 import java.text.ParsePosition;
16 import java.text.SimpleDateFormat;
17 import java.util.Date;
18 import java.util.Locale;
19 import java.util.Hashtable;
20 import java.util.StringTokenizer;
21
22 /**
23  * @author Warren Levy <warrenl@cygnus.com>
24  * @date March 5, 1999.
25  */
26
27 /**
28  * Written using on-line Java Platform 1.2 API Specification, as well
29  * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
30  * Status:  Two guessContentTypeFrom... methods not implemented.
31  *      getContent method assumes content type from response; see comment there.
32  */
33
34 public abstract class URLConnection
35 {
36   protected URL url;
37   protected boolean doInput = true;
38   protected boolean doOutput = false;
39   protected boolean allowUserInteraction;
40   protected boolean useCaches;
41   protected long ifModifiedSince = 0L;
42   protected boolean connected = false;
43   private static boolean defaultAllowUserInteraction = false;
44   private static boolean defaultUseCaches = true;
45   private static FileNameMap fileNameMap;  // Set by the URLConnection subclass.
46   private static ContentHandlerFactory factory;
47   private static ContentHandler contentHandler;
48   private static Hashtable handlers = new Hashtable();
49   private static Locale locale = new Locale("En", "Us", "Unix");
50   private static SimpleDateFormat dateFormat1 =
51           new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss 'GMT'", locale);
52   private static SimpleDateFormat dateFormat2 =
53           new SimpleDateFormat("EEEE, dd-MMM-yy hh:mm:ss 'GMT'", locale);
54   private static SimpleDateFormat dateFormat3 =
55           new SimpleDateFormat("EEE MMM d hh:mm:ss yyyy", locale);
56
57   protected URLConnection(URL url)
58   {
59     this.url = url;
60     allowUserInteraction = defaultAllowUserInteraction;
61     useCaches = defaultUseCaches;
62   }
63
64   public abstract void connect() throws IOException;
65
66   public URL getURL()
67   {
68     return url;
69   }
70
71   public int getContentLength()
72   {
73     return getHeaderFieldInt("content-length", -1);
74   }
75
76   public String getContentType()
77   {
78     return getHeaderField("content-type");
79   }
80
81   public String getContentEncoding()
82   {
83     return getHeaderField("content-encoding");
84   }
85
86   public long getExpiration()
87   {
88     return getHeaderFieldDate("expiration", 0L);
89   }
90
91   public long getDate()
92   {
93     return getHeaderFieldDate("date", 0L);
94   }
95
96   public long getLastModified()
97   {
98     return getHeaderFieldDate("last-modified", 0L);
99   }
100
101   public String getHeaderField(int n)
102   {
103     // Subclasses for specific protocols override this.
104     return null;
105   }
106
107   public String getHeaderField(String name)
108   {
109     // Subclasses for specific protocols override this.
110     return null;
111   }
112
113   public int getHeaderFieldInt(String name, int val)
114   {
115     String str = getHeaderField(name);
116     try
117       {
118         if (str != null)
119           val = Integer.parseInt(str);
120       }
121     catch (NumberFormatException e)
122       {
123         ; // Do nothing; val is the default.
124       }
125     return val;
126   }
127
128   public long getHeaderFieldDate(String name, long val)
129   {
130     String str = getHeaderField(name);
131     if (str != null)
132       {
133         Date date;
134         if ((date = dateFormat1.parse(str, new ParsePosition(0))) != null)
135           val = date.getTime();
136         else if ((date = dateFormat2.parse(str, new ParsePosition(0))) != null)
137           val = date.getTime();
138         else if ((date = dateFormat3.parse(str, new ParsePosition(0))) != null)
139           val = date.getTime();
140       }
141     return val;
142   }
143
144   public String getHeaderFieldKey(int n)
145   {
146     // Subclasses for specific protocols override this.
147     return null;
148   }
149
150   public Object getContent() throws IOException
151   {
152     // FIXME: Doc indicates that other criteria should be applied as
153     // heuristics to determine the true content type, e.g. see 
154     // guessContentTypeFromName() and guessContentTypeFromStream methods
155     // as well as FileNameMap class & fileNameMap field & get/set methods.
156     String cType = getContentType();
157     contentHandler = setContentHandler(cType);
158     if (contentHandler == null)
159       return getInputStream();
160
161     return contentHandler.getContent(this);
162   }
163
164 // TODO12:  public Permission getPermission() throws IOException
165 //   {
166 //     // Subclasses may override this.
167 //     return java.security.AllPermission;
168 //   }
169
170   public InputStream getInputStream() throws IOException
171   {
172     // Subclasses for specific protocols override this.
173     throw new UnknownServiceException("Protocol " + url.getProtocol() +
174                         " does not support input.");
175   }
176
177   public OutputStream getOutputStream() throws IOException
178   {
179     // Subclasses for specific protocols override this.
180     throw new UnknownServiceException("Protocol " + url.getProtocol() +
181                         " does not support output.");
182   }
183
184   public String toString()
185   {
186     return this.getClass().getName() + ":" + url.toString();
187   }
188
189   public void setDoInput(boolean doinput)
190   {
191     if (connected)
192       throw new IllegalAccessError("Already connected");
193
194     doInput = doinput;
195   }
196
197   public boolean getDoInput()
198   {
199     return doInput;
200   }
201
202   public void setDoOutput(boolean dooutput)
203   {
204     if (connected)
205       throw new IllegalAccessError("Already connected");
206
207     doOutput = dooutput;
208     if (doOutput)
209       doInput = false;
210   }
211
212   public boolean getDoOutput()
213   {
214     return doOutput;
215   }
216
217   public void setAllowUserInteraction(boolean allowuserinteraction)
218   {
219     if (connected)
220       throw new IllegalAccessError("Already connected");
221
222     allowUserInteraction = allowuserinteraction;
223   }
224
225   public boolean getAllowUserInteraction()
226   {
227     return allowUserInteraction;
228   }
229
230   public static void
231     setDefaultAllowUserInteraction(boolean defaultallowuserinteraction)
232   {
233     defaultAllowUserInteraction = defaultallowuserinteraction;
234   }
235
236   public static boolean getDefaultAllowUserInteraction()
237   {
238     return defaultAllowUserInteraction;
239   }
240
241   public void setUseCaches(boolean usecaches)
242   {
243     if (connected)
244       throw new IllegalAccessError("Already connected");
245
246     useCaches = usecaches;
247   }
248
249   public boolean getUseCaches()
250   {
251     return useCaches;
252   }
253
254   public void setIfModifiedSince(long ifmodifiedsince)
255   {
256     if (connected)
257       throw new IllegalAccessError("Already connected");
258
259     ifModifiedSince = ifmodifiedsince;
260   }
261
262   public long getIfModifiedSince()
263   {
264     return ifModifiedSince;
265   }
266
267   public boolean getDefaultUseCaches()
268   {
269     return defaultUseCaches;
270   }
271
272   public void setDefaultUseCaches(boolean defaultusecaches)
273   {
274     defaultUseCaches = defaultusecaches;
275   }
276
277   public void setRequestProperty(String key, String value)
278   {
279     // Do nothing unless overridden by subclasses that support setting
280     // header fields in the request.
281   }
282
283   public String getRequestProperty(String key)
284   {
285     // Overridden by subclasses that support reading header fields from the
286     // request.
287     return null;
288   }
289
290   public static void setDefaultRequestProperty(String key, String value)
291   {
292     // Do nothing unless overridden by subclasses that support setting
293     // default request properties.
294   }
295
296   public static String getDefaultRequestProperty(String key)
297   {
298     // Overridden by subclasses that support default request properties.
299     return null;
300   }
301
302   public static void setContentHandlerFactory(ContentHandlerFactory fac)
303   {
304     if (factory != null)
305       throw new Error("ContentHandlerFactory already set");
306
307     // Throw an exception if an extant security mgr precludes
308     // setting the factory.
309     SecurityManager s = System.getSecurityManager();
310     if (s != null)
311       s.checkSetFactory();
312     factory = fac;
313   }
314
315 // TODO:  protected static String guessContentTypeFromName(String fname)
316 //   {
317 //   }
318
319 // TODO:  public static String guessContentTypeFromStream(InputStream is)
320 //          throws IOException
321 //   {
322 //   }
323
324 // TODO12:  protected void parseURL(URL u, String spec, int start, int limit)
325
326   // JDK1.2
327   public static FileNameMap getFileNameMap()
328   {
329     return fileNameMap;
330   }
331
332   // JDK1.2
333   public static void setFileNameMap(FileNameMap map)
334   {
335     // Throw an exception if an extant security mgr precludes
336     // setting the factory.
337     SecurityManager s = System.getSecurityManager();
338     if (s != null)
339       s.checkSetFactory();
340
341     fileNameMap = map;
342   }
343
344   private ContentHandler setContentHandler(String contentType)
345   {
346     ContentHandler handler;
347
348     // No content type so just handle it as the default.
349     if (contentType == null || contentType == "")
350       return null;
351
352     // See if a handler has been cached for this content type.
353     // For efficiency, if a content type has been searched for but not
354     // found, it will be in the hash table but as the contentType String
355     // instead of a ContentHandler.
356     if ((handler = (ContentHandler) handlers.get(contentType)) != null)
357       if (handler instanceof ContentHandler)
358         return handler;
359       else
360         return null;
361
362     // If a non-default factory has been set, use it to find the content type.
363     if (factory != null)
364       handler = factory.createContentHandler(contentType);
365
366     // Non-default factory may have returned null or a factory wasn't set.
367     // Use the default search algorithm to find a handler for this content type.
368     if (handler == null)
369       {
370         // Get the list of packages to check and append our default handler
371         // to it, along with the JDK specified default as a last resort.
372         // Except in very unusual environments the JDK specified one shouldn't
373         // ever be needed (or available).
374         String propVal = System.getProperty("java.content.handler.pkgs");
375         propVal = (propVal == null) ? "" : (propVal + "|");
376         propVal = propVal + "gnu.gcj.content|sun.net.www.content";
377
378         // Replace the '/' character in the content type with '.' and
379         // all other non-alphabetic, non-numeric characters with '_'.
380         StringTokenizer pkgPrefix = new StringTokenizer(propVal, "|");
381         char[] cArray = contentType.toCharArray();
382         for (int i = 0; i < cArray.length; i++)
383           {
384             if (cArray[i] == '/')
385               cArray[i] = '.';
386             else if (! ((cArray[i] >= 'A' && cArray[i] <= 'Z') || 
387                         (cArray[i] >= 'a' && cArray[i] <= 'z') ||
388                         (cArray[i] >= '0' && cArray[i] <= '9')))
389               cArray[i] = '_';
390           }
391         String contentClass = new String(cArray);
392
393         // See if a class of this content type exists in any of the packages.
394         do
395           {
396             String facName = pkgPrefix.nextToken() + "." + contentClass;
397             try
398               {
399                 handler =
400                   (ContentHandler) Class.forName(facName).newInstance();
401               }
402             catch (Exception e)
403               {
404                 // Can't instantiate; handler still null, go on to next element.
405               }
406           } while ((handler == null ||
407                     ! (handler instanceof ContentHandler)) &&
408                    pkgPrefix.hasMoreTokens());
409       }
410
411     // Update the hashtable with the new content handler.
412     if (handler != null && handler instanceof ContentHandler)
413       {
414         handlers.put(contentType, handler);
415         return handler;
416       }
417
418     // For efficiency on subsequent searches, put a dummy entry in the hash
419     // table for content types that don't have a non-default ContentHandler.
420     handlers.put(contentType, contentType);
421     return null;
422   }
423 }