/*
* @(#)FileURLConnection.java 1.58 06/10/10
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*
*/
/**
* Open an file input stream given a URL.
* @author James Gosling
* @author Steven B. Byrne
* @version 1.48, 05/03/00
*/
package sun.net.www.protocol.file;
import java.net.URL;
import java.net.FileNameMap;
import java.io.*;
/* Remove the sorting ability because of cutting
the following java.text.* dependency.
java/text/CharacterIterator
java/text/CollationElementIterator
java/text/CollationKey
java/text/CollationRules
java/text/Collator
java/text/CompactByteArray
java/text/CompactIntArray
java/text/CompactShortArray
java/text/EntryPair
java/text/IntHashtable
java/text/MergeCollation
java/text/Normalizer
java/text/PatternEntry
java/text/RBCollationTables
java/text/RBTableBuilder
java/text/RuleBasedCollator
java/text/StringCharacterIterator
import java.text.Collator;
*/
import java.security.Permission;
import sun.net.*;
import sun.net.www.*;
import java.util.*;
import java.text.SimpleDateFormat;
import sun.security.action.GetPropertyAction;
import sun.security.action.GetIntegerAction;
import sun.security.action.GetBooleanAction;
public class FileURLConnection extends URLConnection {
static String CONTENT_LENGTH = "content-length";
static String CONTENT_TYPE = "content-type";
static String TEXT_PLAIN = "text/plain";
static String LAST_MODIFIED = "last-modified";
String contentType;
InputStream is;
File file;
String filename;
boolean isDirectory = false;
boolean exists = false;
List files;
long length = 0;
long lastModified = 0;
protected FileURLConnection(URL u, File file) {
super(u);
this.file = file;
}
/*
* Note: the semantics of FileURLConnection object is that the
* results of the various URLConnection calls, such as
* getContentType, getInputStream or getContentLength reflect
* whatever was true when connect was called.
*/
public void connect() throws IOException {
if (!connected) {
try {
String decodedPath = ParseUtil.decode(url.getPath());
file = new File(decodedPath.replace('/', File.separatorChar));
filename = file.toString();
isDirectory = file.isDirectory();
if (isDirectory) {
files = (List) Arrays.asList(file.list());
} else {
is = new BufferedInputStream(chainDecorator(new FileInputStream(filename)));
}
} catch (IOException e) {
throw e;
}
connected = true;
}
}
/*
* To be overridden by subclasses, e.g. Java Plug-in.
*/
protected InputStream chainDecorator(InputStream s)
{
return s;
}
private boolean initializedHeaders = false;
private void initializeHeaders() {
try {
connect();
exists = file.exists();
} catch (IOException e) {
}
if (!initializedHeaders || !exists) {
length = file.length();
lastModified = file.lastModified();
if (!isDirectory) {
FileNameMap map = java.net.URLConnection.getFileNameMap();
contentType = map.getContentTypeFor(filename);
if (contentType != null) {
properties.add(CONTENT_TYPE, contentType);
}
properties.add(CONTENT_LENGTH, String.valueOf(length));
/*
* Format the last-modified field into the preferred
* Internet standard - ie: fixed-length subset of that
* defined by RFC 1123
*/
if (lastModified != 0) {
Date date = new Date(lastModified);
SimpleDateFormat fo =
new SimpleDateFormat ("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
fo.setTimeZone(TimeZone.getTimeZone("GMT"));
properties.add(LAST_MODIFIED, fo.format(date));
}
} else {
properties.add(CONTENT_TYPE, TEXT_PLAIN);
}
initializedHeaders = true;
}
}
public String getHeaderField(String name) {
initializeHeaders();
return super.getHeaderField(name);
}
public String getHeaderField(int n) {
initializeHeaders();
return super.getHeaderField(n);
}
public int getContentLength() {
initializeHeaders();
return super.getContentLength();
}
public String getHeaderFieldKey(int n) {
initializeHeaders();
return super.getHeaderFieldKey(n);
}
public MessageHeader getProperties() {
initializeHeaders();
return super.getProperties();
}
public synchronized InputStream getInputStream()
throws IOException {
int iconHeight;
int iconWidth;
connect();
if (is == null) {
iconHeight = ((Integer)java.security.AccessController.doPrivileged(
new GetIntegerAction("hotjava.file.iconheight",
32))).intValue();
iconWidth = ((Integer)java.security.AccessController.doPrivileged(
new GetIntegerAction("hotjava.file.iconwidth",
32))).intValue();
if (isDirectory) {
FileNameMap map = java.net.URLConnection.getFileNameMap();
StringBuffer buf = new StringBuffer();
if (files == null) {
throw new FileNotFoundException(filename);
}
/* Comment this out because of dependency cut. 4/5/2000
* Collections.sort(files, Collator.getInstance());
*/
buf.append("<title>");
buf.append((String)java.security.AccessController.doPrivileged(
new GetPropertyAction("file.dir.title",
"Directory Listing")));
buf.append("</title>\n");
buf.append("<base href=\"file://localhost/");
buf.append(filename.substring((filename.charAt(0) == '/') ? 1 : 0));
if (filename.endsWith("/")) {
buf.append("\">");
} else {
buf.append("/\">");
}
buf.append("<h1>");
buf.append(filename);
buf.append("</h1>\n");
buf.append("<hr>\n");
Boolean tmp;
tmp = (Boolean) java.security.AccessController.doPrivileged(
new GetBooleanAction("file.hidedotfiles"));
boolean hideDotFiles = tmp.booleanValue();
for (int i = 0 ; i < files.size() ; i++) {
String fileName = (String)files.get(i);
if (hideDotFiles) {
if (fileName.indexOf('.') == 0) {
continue;
}
}
buf.append("<img align=middle src=\"");
if (new File(filename + "/" + fileName).isDirectory()) {
buf.append(MimeEntry.defaultImagePath +
"/directory.gif\" width="+iconWidth+
" height="+iconHeight+">\n");
} else {
String imageFileName = MimeEntry.defaultImagePath +
"/file.gif";
if (map instanceof MimeTable) {
MimeEntry entry =
((MimeTable)map).findByFileName(fileName);
if (entry != null) {
String realImageName =
entry.getImageFileName();
if (realImageName != null) {
imageFileName = realImageName;
}
}
}
buf.append(imageFileName);
buf.append("\" width="+iconWidth+" height="+iconHeight+
">\n");
}
buf.append("<a href=\"");
buf.append(fileName);
buf.append("\">");
buf.append(fileName);
buf.append("</a><br>");
}
// Put it into a (default) locale-specific byte-stream.
is = new ByteArrayInputStream(buf.toString().getBytes());
} else {
throw new FileNotFoundException(filename);
}
}
return is;
}
Permission permission;
/* since getOutputStream isn't supported, only read permission is
* relevant
*/
public Permission getPermission() throws IOException {
if (permission == null) {
String decodedPath = ParseUtil.decode(url.getPath());
if (File.separatorChar == '/') {
permission = new FilePermission(decodedPath, "read");
} else {
permission = new FilePermission(
decodedPath.replace('/',File.separatorChar), "read");
}
}
return permission;
}
}