1 /* FileURLConnection.java -- URLConnection class for "file" protocol
2 Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu
.java
.net
.protocol
.file
;
40 import gnu
.classpath
.SystemProperties
;
42 import java
.io
.BufferedInputStream
;
43 import java
.io
.BufferedOutputStream
;
44 import java
.io
.ByteArrayInputStream
;
45 import java
.io
.ByteArrayOutputStream
;
47 import java
.io
.FileInputStream
;
48 import java
.io
.FileOutputStream
;
49 import java
.io
.FilePermission
;
50 import java
.io
.IOException
;
51 import java
.io
.InputStream
;
52 import java
.io
.OutputStream
;
53 import java
.io
.OutputStreamWriter
;
54 import java
.io
.Writer
;
55 import java
.net
.ProtocolException
;
57 import java
.net
.URLConnection
;
58 import java
.security
.Permission
;
59 import java
.text
.SimpleDateFormat
;
60 import java
.util
.Date
;
61 import java
.util
.Locale
;
62 import java
.net
.MalformedURLException
;
65 * This subclass of java.net.URLConnection models a URLConnection via
66 * the "file" protocol.
68 * @author Aaron M. Renn (arenn@urbanophile.com)
69 * @author Nic Ferrier (nferrier@tapsellferrier.co.uk)
70 * @author Warren Levy (warrenl@cygnus.com)
72 public class Connection
extends URLConnection
75 * Default permission for a file
77 private static final String DEFAULT_PERMISSION
= "read";
79 private static class StaticData
82 * HTTP-style DateFormat, used to format the last-modified header.
84 static SimpleDateFormat dateFormat
85 = new SimpleDateFormat("EEE, dd MMM yyyy hh:mm:ss 'GMT'",
86 new Locale ("En", "Us", "Unix"));
88 static String lineSeparator
=
89 SystemProperties
.getProperty("line.separator");
94 * This is a File object for this connection
99 * If a directory, contains a list of files in the directory.
101 private byte[] directoryListing
;
104 * InputStream if we are reading from the file
106 private InputStream inputStream
;
109 * OutputStream if we are writing to the file
111 private OutputStream outputStream
;
114 * FilePermission to read the file
116 private FilePermission permission
;
119 * Calls superclass constructor to initialize.
121 public Connection(URL url
)
125 permission
= new FilePermission(getURL().getFile(), DEFAULT_PERMISSION
);
129 * Unquote "%" + hex quotes characters
131 * @param str The string to unquote or null.
133 * @return The unquoted string or null if str was null.
135 * @exception MalformedURLException If the given string contains invalid
139 public static String
unquote(String str
) throws MalformedURLException
144 final int MAX_BYTES_PER_UTF_8_CHAR
= 3;
145 byte[] buf
= new byte[str
.length()*MAX_BYTES_PER_UTF_8_CHAR
];
147 for (int i
= 0; i
< str
.length(); i
++)
149 char c
= str
.charAt(i
);
152 if (i
+ 2 >= str
.length())
153 throw new MalformedURLException(str
+ " : Invalid quoted character");
154 int hi
= Character
.digit(str
.charAt(++i
), 16);
155 int lo
= Character
.digit(str
.charAt(++i
), 16);
156 if (lo
< 0 || hi
< 0)
157 throw new MalformedURLException(str
+ " : Invalid quoted character");
158 buf
[pos
++] = (byte) (hi
* 16 + lo
);
162 byte [] c_as_bytes
= Character
.toString(c
).getBytes("utf-8");
163 System
.arraycopy(c_as_bytes
, 0, buf
, pos
, c_as_bytes
.length
);
165 catch (java
.io
.UnsupportedEncodingException x2
) {
166 throw (Error
) new InternalError().initCause(x2
);
170 buf
[pos
++] = (byte) c
;
174 return new String(buf
, 0, pos
, "utf-8");
176 catch (java
.io
.UnsupportedEncodingException x2
)
178 throw (Error
) new InternalError().initCause(x2
);
183 * "Connects" to the file by opening it.
185 public void connect() throws IOException
187 // Call is ignored if already connected.
191 // If not connected, then file needs to be openned.
192 file
= new File (unquote(getURL().getFile()));
194 if (! file
.isDirectory())
197 inputStream
= new BufferedInputStream(new FileInputStream(file
));
200 outputStream
= new BufferedOutputStream(new FileOutputStream(file
));
206 inputStream
= new ByteArrayInputStream(getDirectoryListing());
210 throw new ProtocolException
211 ("file: protocol does not support output on directories");
218 * Populates the <code>directoryListing</code> field with a byte array
219 * containing a representation of the directory listing.
221 byte[] getDirectoryListing()
224 if (directoryListing
== null)
226 ByteArrayOutputStream sink
= new ByteArrayOutputStream();
227 // NB uses default character encoding for this system
228 Writer writer
= new OutputStreamWriter(sink
);
230 String
[] files
= file
.list();
232 for (int i
= 0; i
< files
.length
; i
++)
234 writer
.write(files
[i
]);
235 writer
.write(StaticData
.lineSeparator
);
238 directoryListing
= sink
.toByteArray();
240 return directoryListing
;
244 * Opens the file for reading and returns a stream for it.
246 * @return An InputStream for this connection.
248 * @exception IOException If an error occurs
250 public InputStream
getInputStream()
254 throw new ProtocolException("Can't open InputStream if doInput is false");
263 * Opens the file for writing and returns a stream for it.
265 * @return An OutputStream for this connection.
267 * @exception IOException If an error occurs.
269 public OutputStream
getOutputStream()
274 ProtocolException("Can't open OutputStream if doOutput is false");
283 * Get the last modified time of the resource.
285 * @return the time since epoch that the resource was modified.
287 public long getLastModified()
294 return file
.lastModified();
296 catch (IOException e
)
303 * Get an http-style header field. Just handle a few common ones.
305 public String
getHeaderField(String field
)
312 if (field
.equals("content-type"))
313 return guessContentTypeFromName(file
.getName());
314 else if (field
.equals("content-length"))
316 if (file
.isDirectory())
318 return Integer
.toString(getContentLength());
320 return Long
.toString(file
.length());
322 else if (field
.equals("last-modified"))
324 synchronized (StaticData
.dateFormat
)
326 return StaticData
.dateFormat
.format(
327 new Date(file
.lastModified()));
331 catch (IOException e
)
339 * Get the length of content.
341 * @return the length of the content.
343 public int getContentLength()
350 if (file
.isDirectory())
352 return getDirectoryListing().length
;
354 return (int) file
.length();
356 catch (IOException e
)
363 * This method returns a <code>Permission</code> object representing the
364 * permissions required to access this URL. This method returns a
365 * <code>java.io.FilePermission</code> for the file's path with a read
368 * @return A Permission object
370 public Permission
getPermission() throws IOException