001: /*
002: * @(#)FileURLConnection.java 1.57 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: /**
029: * Open an file input stream given a URL.
030: * @author James Gosling
031: * @author Steven B. Byrne
032: * @version 1.51, 11/06/00
033: */package sun.net.www.protocol.file;
034:
035: import java.net.URL;
036: import java.net.FileNameMap;
037: import java.io.*;
038: import java.text.Collator;
039: import java.security.Permission;
040: import sun.net.*;
041: import sun.net.www.*;
042: import java.util.*;
043: import java.text.SimpleDateFormat;
044:
045: import sun.security.action.GetPropertyAction;
046: import sun.security.action.GetIntegerAction;
047: import sun.security.action.GetBooleanAction;
048:
049: public class FileURLConnection extends URLConnection {
050:
051: static String CONTENT_LENGTH = "content-length";
052: static String CONTENT_TYPE = "content-type";
053: static String TEXT_PLAIN = "text/plain";
054: static String LAST_MODIFIED = "last-modified";
055:
056: String contentType;
057: InputStream is;
058:
059: File file;
060: String filename;
061: boolean isDirectory = false;
062: boolean exists = false;
063: List files;
064:
065: long length = 0;
066: long lastModified = 0;
067:
068: protected FileURLConnection(URL u, File file) {
069: super (u);
070: this .file = file;
071: }
072:
073: /*
074: * Note: the semantics of FileURLConnection object is that the
075: * results of the various URLConnection calls, such as
076: * getContentType, getInputStream or getContentLength reflect
077: * whatever was true when connect was called.
078: */
079: public void connect() throws IOException {
080: if (!connected) {
081: try {
082: filename = file.toString();
083: isDirectory = file.isDirectory();
084: if (isDirectory) {
085: files = (List) Arrays.asList(file.list());
086: } else {
087: is = new BufferedInputStream(
088: chainDecorator(new FileInputStream(filename)));
089: }
090: } catch (IOException e) {
091: throw e;
092: }
093: connected = true;
094: }
095: }
096:
097: /*
098: * To be overridden by subclasses, e.g. Java Plug-in.
099: */
100: protected InputStream chainDecorator(InputStream s) {
101: return s;
102: }
103:
104: private boolean initializedHeaders = false;
105:
106: private void initializeHeaders() {
107: try {
108: connect();
109: exists = file.exists();
110: } catch (IOException e) {
111: }
112: if (!initializedHeaders || !exists) {
113: length = file.length();
114: lastModified = file.lastModified();
115:
116: if (!isDirectory) {
117: FileNameMap map = java.net.URLConnection
118: .getFileNameMap();
119: contentType = map.getContentTypeFor(filename);
120: if (contentType != null) {
121: properties.add(CONTENT_TYPE, contentType);
122: }
123: properties.add(CONTENT_LENGTH, String.valueOf(length));
124:
125: /*
126: * Format the last-modified field into the preferred
127: * Internet standard - ie: fixed-length subset of that
128: * defined by RFC 1123
129: */
130: if (lastModified != 0) {
131: Date date = new Date(lastModified);
132: SimpleDateFormat fo = new SimpleDateFormat(
133: "EEE, dd MMM yyyy HH:mm:ss 'GMT'",
134: Locale.US);
135: fo.setTimeZone(TimeZone.getTimeZone("GMT"));
136: properties.add(LAST_MODIFIED, fo.format(date));
137: }
138: } else {
139: properties.add(CONTENT_TYPE, TEXT_PLAIN);
140: }
141: initializedHeaders = true;
142: }
143: }
144:
145: public String getHeaderField(String name) {
146: initializeHeaders();
147: return super .getHeaderField(name);
148: }
149:
150: public String getHeaderField(int n) {
151: initializeHeaders();
152: return super .getHeaderField(n);
153: }
154:
155: public int getContentLength() {
156: initializeHeaders();
157: return super .getContentLength();
158: }
159:
160: public String getHeaderFieldKey(int n) {
161: initializeHeaders();
162: return super .getHeaderFieldKey(n);
163: }
164:
165: public MessageHeader getProperties() {
166: initializeHeaders();
167: return super .getProperties();
168: }
169:
170: public synchronized InputStream getInputStream() throws IOException {
171:
172: int iconHeight;
173: int iconWidth;
174:
175: connect();
176:
177: if (is == null) {
178: iconHeight = ((Integer) java.security.AccessController
179: .doPrivileged(new GetIntegerAction(
180: "hotjava.file.iconheight", 32))).intValue();
181: iconWidth = ((Integer) java.security.AccessController
182: .doPrivileged(new GetIntegerAction(
183: "hotjava.file.iconwidth", 32))).intValue();
184: if (isDirectory) {
185: FileNameMap map = java.net.URLConnection
186: .getFileNameMap();
187:
188: StringBuffer buf = new StringBuffer();
189:
190: if (files == null) {
191: throw new FileNotFoundException(filename);
192: }
193:
194: Collections.sort(files, Collator.getInstance());
195:
196: buf.append("<title>");
197: buf
198: .append((String) java.security.AccessController
199: .doPrivileged(new GetPropertyAction(
200: "file.dir.title",
201: "Directory Listing")));
202: buf.append("</title>\n");
203: buf.append("<base href=\"file://localhost/");
204: buf
205: .append(filename
206: .substring((filename.charAt(0) == '/') ? 1
207: : 0));
208: if (filename.endsWith("/")) {
209: buf.append("\">");
210: } else {
211: buf.append("/\">");
212: }
213: buf.append("<h1>");
214: buf.append(filename);
215: buf.append("</h1>\n");
216: buf.append("<hr>\n");
217:
218: Boolean tmp;
219: tmp = (Boolean) java.security.AccessController
220: .doPrivileged(new GetBooleanAction(
221: "file.hidedotfiles"));
222: boolean hideDotFiles = tmp.booleanValue();
223: for (int i = 0; i < files.size(); i++) {
224: String fileName = (String) files.get(i);
225:
226: if (hideDotFiles) {
227: if (fileName.indexOf('.') == 0) {
228: continue;
229: }
230: }
231:
232: buf.append("<img align=middle src=\"");
233: if (new File(filename + "/" + fileName)
234: .isDirectory()) {
235: buf.append(MimeEntry.defaultImagePath
236: + "/directory.gif\" width=" + iconWidth
237: + " height=" + iconHeight + ">\n");
238: } else {
239: String imageFileName = MimeEntry.defaultImagePath
240: + "/file.gif";
241:
242: if (map instanceof MimeTable) {
243: MimeEntry entry = ((MimeTable) map)
244: .findByFileName(fileName);
245: if (entry != null) {
246: String realImageName = entry
247: .getImageFileName();
248: if (realImageName != null) {
249: imageFileName = realImageName;
250: }
251: }
252: }
253:
254: buf.append(imageFileName);
255: buf.append("\" width=" + iconWidth + " height="
256: + iconHeight + ">\n");
257: }
258: buf.append("<a href=\"");
259: buf.append("\">");
260: buf.append(fileName);
261: buf.append("</a><br>");
262: }
263: // Put it into a (default) locale-specific byte-stream.
264: is = new ByteArrayInputStream(buf.toString().getBytes());
265: } else {
266: throw new FileNotFoundException(filename);
267: }
268: }
269: return is;
270: }
271:
272: Permission permission;
273:
274: /* since getOutputStream isn't supported, only read permission is
275: * relevant
276: */
277: public Permission getPermission() throws IOException {
278: if (permission == null) {
279: String decodedPath = ParseUtil.decode(url.getPath());
280: if (File.separatorChar == '/') {
281: permission = new FilePermission(decodedPath, "read");
282: } else {
283: permission = new FilePermission(decodedPath.replace(
284: '/', File.separatorChar), "read");
285: }
286: }
287: return permission;
288: }
289: }
|