1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package org.apache.harmony.luni.internal.net.www.protocol.file; 19 20import java.io.BufferedInputStream; 21import java.io.ByteArrayInputStream; 22import java.io.ByteArrayOutputStream; 23import java.io.File; 24import java.io.FileInputStream; 25import java.io.FilePermission; 26import java.io.IOException; 27import java.io.InputStream; 28import java.io.PrintStream; 29import java.net.URL; 30import java.net.URLConnection; 31 32import org.apache.harmony.luni.internal.net.www.MimeTable; 33import org.apache.harmony.luni.util.Util; 34 35/** 36 * This subclass extends <code>URLConnection</code>. 37 * <p> 38 * This class is responsible for connecting, getting content and input stream of 39 * the file. 40 */ 41public class FileURLConnection extends URLConnection { 42 43 String fileName; 44 45 private InputStream is; 46 47 private int length = -1; 48 49 private boolean isDir; 50 51 private FilePermission permission; 52 53 /** 54 * Creates an instance of <code>FileURLConnection</code> for establishing 55 * a connection to the file pointed by this <code>URL<code> 56 * 57 * @param url The URL this connection is connected to 58 */ 59 public FileURLConnection(URL url) { 60 super(url); 61 fileName = url.getFile(); 62 if (fileName == null) { 63 fileName = ""; //$NON-NLS-1$ 64 } 65 fileName = Util.decode(fileName, false); 66 } 67 68 /** 69 * This methods will attempt to obtain the input stream of the file pointed 70 * by this <code>URL</code>. If the file is a directory, it will return 71 * that directory listing as an input stream. 72 * 73 * @throws IOException 74 * if an IO error occurs while connecting 75 */ 76 @Override 77 public void connect() throws IOException { 78 File f = new File(fileName); 79 if (f.isDirectory()) { 80 isDir = true; 81 is = getDirectoryListing(f); 82 // use -1 for the contentLength 83 } else { 84 // BEGIN android-modified 85 is = new BufferedInputStream(new FileInputStream(f), 8192); 86 // END android-modified 87 length = is.available(); 88 } 89 connected = true; 90 } 91 92 /** 93 * Returns the length of the file in bytes. 94 * 95 * @return the length of the file 96 * 97 * @see #getContentType() 98 */ 99 @Override 100 public int getContentLength() { 101 try { 102 if (!connected) { 103 connect(); 104 } 105 } catch (IOException e) { 106 // default is -1 107 } 108 return length; 109 } 110 111 /** 112 * Returns the content type of the resource. Just takes a guess based on the 113 * name. 114 * 115 * @return the content type 116 */ 117 @Override 118 public String getContentType() { 119 try { 120 if (!connected) { 121 connect(); 122 } 123 } catch (IOException e) { 124 return MimeTable.UNKNOWN; 125 } 126 if (isDir) { 127 return "text/plain"; //$NON-NLS-1$ 128 } 129 String result = guessContentTypeFromName(url.getFile()); 130 if (result != null) { 131 return result; 132 } 133 134 try { 135 result = guessContentTypeFromStream(is); 136 } catch (IOException e) { 137 // Ignore 138 } 139 if (result != null) { 140 return result; 141 } 142 143 return MimeTable.UNKNOWN; 144 } 145 146 /** 147 * Returns the directory listing of the file component as an input stream. 148 * 149 * @return the input stream of the directory listing 150 */ 151 private InputStream getDirectoryListing(File f) { 152 String fileList[] = f.list(); 153 ByteArrayOutputStream bytes = new java.io.ByteArrayOutputStream(); 154 PrintStream out = new PrintStream(bytes); 155 out.print("<title>Directory Listing</title>\n"); //$NON-NLS-1$ 156 out.print("<base href=\"file:"); //$NON-NLS-1$ 157 out.print(f.getPath().replace('\\', '/') + "/\"><h1>" + f.getPath() //$NON-NLS-1$ 158 + "</h1>\n<hr>\n"); //$NON-NLS-1$ 159 int i; 160 for (i = 0; i < fileList.length; i++) { 161 out.print(fileList[i] + "<br>\n"); //$NON-NLS-1$ 162 } 163 out.close(); 164 return new ByteArrayInputStream(bytes.toByteArray()); 165 } 166 167 /** 168 * Returns the input stream of the object referred to by this 169 * <code>URLConnection</code> 170 * 171 * File Sample : "/ZIP211/+/harmony/tools/javac/resources/javac.properties" 172 * Invalid File Sample: 173 * "/ZIP/+/harmony/tools/javac/resources/javac.properties" 174 * "ZIP211/+/harmony/tools/javac/resources/javac.properties" 175 * 176 * @return input stream of the object 177 * 178 * @throws IOException 179 * if an IO error occurs 180 */ 181 @Override 182 public InputStream getInputStream() throws IOException { 183 if (!connected) { 184 connect(); 185 } 186 return is; 187 } 188 189 /** 190 * Returns the permission, in this case the subclass, FilePermission object 191 * which represents the permission necessary for this URLConnection to 192 * establish the connection. 193 * 194 * @return the permission required for this URLConnection. 195 * 196 * @throws IOException 197 * if an IO exception occurs while creating the permission. 198 */ 199 @Override 200 public java.security.Permission getPermission() throws IOException { 201 if (permission == null) { 202 String path = fileName; 203 if (File.separatorChar != '/') { 204 path = path.replace('/', File.separatorChar); 205 } 206 permission = new FilePermission(path, "read"); //$NON-NLS-1$ 207 } 208 return permission; 209 } 210} 211