001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.luni.internal.net.www.protocol.file;
019:
020: import java.io.BufferedInputStream;
021: import java.io.ByteArrayInputStream;
022: import java.io.ByteArrayOutputStream;
023: import java.io.File;
024: import java.io.FileInputStream;
025: import java.io.FilePermission;
026: import java.io.IOException;
027: import java.io.InputStream;
028: import java.io.PrintStream;
029: import java.net.URL;
030: import java.net.URLConnection;
031:
032: import org.apache.harmony.luni.internal.net.www.MimeTable;
033: import org.apache.harmony.luni.util.Util;
034:
035: /**
036: * This subclass extends <code>URLConnection</code>.
037: * <p>
038: * This class is responsible for connecting, getting content and input stream of
039: * the file.
040: */
041: public class FileURLConnection extends URLConnection {
042:
043: String fileName;
044:
045: private InputStream is;
046:
047: private int length = -1;
048:
049: private boolean isDir;
050:
051: private FilePermission permission;
052:
053: /**
054: * Creates an instance of <code>FileURLConnection</code> for establishing
055: * a connection to the file pointed by this <code>URL<code>
056: *
057: * @param url The URL this connection is connected to
058: */
059: public FileURLConnection(URL url) {
060: super (url);
061: fileName = url.getFile();
062: if (url.getRef() != null) {
063: fileName += "#" + url.getRef(); //$NON-NLS-1$
064: }
065: if (fileName == null) {
066: fileName = ""; //$NON-NLS-1$
067: }
068: String host = url.getHost();
069: if (host != null && host.length() > 0) {
070: fileName = "//" + host + fileName; //$NON-NLS-1$
071: }
072: fileName = Util.decode(fileName, false);
073: }
074:
075: /**
076: * This methods will attempt to obtain the input stream of the file pointed
077: * by this <code>URL</code>. If the file is a directory, it will return
078: * that directory listing as an input stream.
079: *
080: * @throws IOException
081: * if an IO error occurs while connecting
082: */
083: @Override
084: public void connect() throws IOException {
085: File f = new File(fileName);
086: if (f.isDirectory()) {
087: isDir = true;
088: is = getDirectoryListing(f);
089: // use -1 for the contentLength
090: } else {
091: is = new BufferedInputStream(new FileInputStream(f));
092: length = is.available();
093: }
094: connected = true;
095: }
096:
097: /**
098: * Answers the length of the file in bytes.
099: *
100: * @return the length of the file
101: *
102: * @see #getContentType()
103: */
104: @Override
105: public int getContentLength() {
106: try {
107: if (!connected) {
108: connect();
109: }
110: } catch (IOException e) {
111: // default is -1
112: }
113: return length;
114: }
115:
116: /**
117: * Answers the content type of the resource. Just takes a guess based on the
118: * name.
119: *
120: * @return the content type
121: */
122: @Override
123: public String getContentType() {
124: try {
125: if (!connected) {
126: connect();
127: }
128: } catch (IOException e) {
129: return MimeTable.UNKNOWN;
130: }
131: if (isDir) {
132: return "text/plain"; //$NON-NLS-1$
133: }
134: String result = guessContentTypeFromName(url.getFile());
135: if (result != null) {
136: return result;
137: }
138:
139: try {
140: result = guessContentTypeFromStream(is);
141: } catch (IOException e) {
142: // Ignore
143: }
144: if (result != null) {
145: return result;
146: }
147:
148: return MimeTable.UNKNOWN;
149: }
150:
151: /**
152: * Answers the directory listing of the file component as an input stream.
153: *
154: * @return the input stream of the directory listing
155: */
156: private InputStream getDirectoryListing(File f) {
157: String fileList[] = f.list();
158: ByteArrayOutputStream bytes = new java.io.ByteArrayOutputStream();
159: PrintStream out = new PrintStream(bytes);
160: out.print("<title>Directory Listing</title>\n"); //$NON-NLS-1$
161: out.print("<base href=\"file:"); //$NON-NLS-1$
162: out.print(f.getPath().replace('\\', '/')
163: + "/\"><h1>" + f.getPath() //$NON-NLS-1$
164: + "</h1>\n<hr>\n"); //$NON-NLS-1$
165: int i;
166: for (i = 0; i < fileList.length; i++) {
167: out.print(fileList[i] + "<br>\n"); //$NON-NLS-1$
168: }
169: out.close();
170: return new ByteArrayInputStream(bytes.toByteArray());
171: }
172:
173: /**
174: * Answers the input stream of the object referred to by this
175: * <code>URLConnection</code>
176: *
177: * File Sample : "/ZIP211/+/harmony/tools/javac/resources/javac.properties"
178: * Invalid File Sample:
179: * "/ZIP/+/harmony/tools/javac/resources/javac.properties"
180: * "ZIP211/+/harmony/tools/javac/resources/javac.properties"
181: *
182: * @return input stream of the object
183: *
184: * @throws IOException
185: * if an IO error occurs
186: */
187: @Override
188: public InputStream getInputStream() throws IOException {
189: if (!connected) {
190: connect();
191: }
192: return is;
193: }
194:
195: /**
196: * Answers the permission, in this case the subclass, FilePermission object
197: * which represents the permission necessary for this URLConnection to
198: * establish the connection.
199: *
200: * @return the permission required for this URLConnection.
201: *
202: * @throws IOException
203: * if an IO exception occurs while creating the permission.
204: */
205: @Override
206: public java.security.Permission getPermission() throws IOException {
207: if (permission == null) {
208: String path = fileName;
209: if (File.separatorChar != '/') {
210: path = path.replace('/', File.separatorChar);
211: }
212: permission = new FilePermission(path, "read"); //$NON-NLS-1$
213: }
214: return permission;
215: }
216: }
|