Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / gnu / java / net / protocol / file / Connection.java
blobf7253b0935be028810af3be0028d3bb52aba7b7f
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)
9 any later version.
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
19 02110-1301 USA.
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
24 combination.
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;
46 import java.io.File;
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;
56 import java.net.URL;
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;
64 /**
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
74 /**
75 * Default permission for a file
77 private static final String DEFAULT_PERMISSION = "read";
79 private static class StaticData
81 /**
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");
93 /**
94 * This is a File object for this connection
96 private File file;
98 /**
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)
123 super (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
136 * escape sequences.
139 public static String unquote(String str) throws MalformedURLException
141 if (str == null)
142 return null;
144 final int MAX_BYTES_PER_UTF_8_CHAR = 3;
145 byte[] buf = new byte[str.length()*MAX_BYTES_PER_UTF_8_CHAR];
146 int pos = 0;
147 for (int i = 0; i < str.length(); i++)
149 char c = str.charAt(i);
150 if (c == '%')
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);
160 else if (c > 127) {
161 try {
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);
169 else
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.
188 if (connected)
189 return;
191 // If not connected, then file needs to be openned.
192 file = new File (unquote(getURL().getFile()));
194 if (! file.isDirectory())
196 if (doInput)
197 inputStream = new BufferedInputStream(new FileInputStream(file));
199 if (doOutput)
200 outputStream = new BufferedOutputStream(new FileOutputStream(file));
202 else
204 if (doInput)
206 inputStream = new ByteArrayInputStream(getDirectoryListing());
209 if (doOutput)
210 throw new ProtocolException
211 ("file: protocol does not support output on directories");
214 connected = true;
218 * Populates the <code>directoryListing</code> field with a byte array
219 * containing a representation of the directory listing.
221 byte[] getDirectoryListing()
222 throws IOException
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()
251 throws IOException
253 if (!doInput)
254 throw new ProtocolException("Can't open InputStream if doInput is false");
256 if (!connected)
257 connect();
259 return inputStream;
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()
270 throws IOException
272 if (!doOutput)
273 throw new
274 ProtocolException("Can't open OutputStream if doOutput is false");
276 if (!connected)
277 connect();
279 return outputStream;
283 * Get the last modified time of the resource.
285 * @return the time since epoch that the resource was modified.
287 public long getLastModified()
291 if (!connected)
292 connect();
294 return file.lastModified();
296 catch (IOException e)
298 return -1;
303 * Get an http-style header field. Just handle a few common ones.
305 public String getHeaderField(String field)
309 if (!connected)
310 connect();
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)
333 // Fall through.
335 return null;
339 * Get the length of content.
341 * @return the length of the content.
343 public int getContentLength()
347 if (!connected)
348 connect();
350 if (file.isDirectory())
352 return getDirectoryListing().length;
354 return (int) file.length();
356 catch (IOException e)
358 return -1;
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
366 * permission.
368 * @return A Permission object
370 public Permission getPermission() throws IOException
372 return permission;