Home | History | Annotate | Download | only in file
      1 /*
      2  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 /**
     27  * Open an file input stream given a URL.
     28  * @author      James Gosling
     29  * @author      Steven B. Byrne
     30  */
     31 
     32 package sun.net.www.protocol.file;
     33 
     34 import java.net.URL;
     35 import java.net.FileNameMap;
     36 import java.io.*;
     37 import java.text.Collator;
     38 import java.security.Permission;
     39 import sun.net.*;
     40 import sun.net.www.*;
     41 import java.util.*;
     42 import java.text.SimpleDateFormat;
     43 
     44 import sun.security.action.GetPropertyAction;
     45 import sun.security.action.GetIntegerAction;
     46 import sun.security.action.GetBooleanAction;
     47 
     48 public class FileURLConnection extends URLConnection {
     49 
     50     static String CONTENT_LENGTH = "content-length";
     51     static String CONTENT_TYPE = "content-type";
     52     static String TEXT_PLAIN = "text/plain";
     53     static String LAST_MODIFIED = "last-modified";
     54 
     55     String contentType;
     56     InputStream is;
     57 
     58     File file;
     59     String filename;
     60     boolean isDirectory = false;
     61     boolean exists = false;
     62     List<String> files;
     63 
     64     long length = -1;
     65     long lastModified = 0;
     66 
     67     protected FileURLConnection(URL u, File file) {
     68         super(u);
     69         this.file = file;
     70     }
     71 
     72     /*
     73      * Note: the semantics of FileURLConnection object is that the
     74      * results of the various URLConnection calls, such as
     75      * getContentType, getInputStream or getContentLength reflect
     76      * whatever was true when connect was called.
     77      */
     78     public void connect() throws IOException {
     79         if (!connected) {
     80             try {
     81                 filename = file.toString();
     82                 isDirectory = file.isDirectory();
     83                 if (isDirectory) {
     84                     String[] fileList = file.list();
     85                     if (fileList == null)
     86                         throw new FileNotFoundException(filename + " exists, but is not accessible");
     87                     files = Arrays.<String>asList(fileList);
     88                 } else {
     89 
     90                     is = new BufferedInputStream(new FileInputStream(filename));
     91 
     92                     // Check if URL should be metered
     93                     boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET");
     94                     if (meteredInput)   {
     95                         ProgressSource pi = new ProgressSource(url, "GET", file.length());
     96                         is = new MeteredStream(is, pi, file.length());
     97                     }
     98                 }
     99             } catch (IOException e) {
    100                 throw e;
    101             }
    102             connected = true;
    103         }
    104     }
    105 
    106     private boolean initializedHeaders = false;
    107 
    108     private void initializeHeaders() {
    109         try {
    110             connect();
    111             exists = file.exists();
    112         } catch (IOException e) {
    113         }
    114         if (!initializedHeaders || !exists) {
    115             length = file.length();
    116             lastModified = file.lastModified();
    117 
    118             if (!isDirectory) {
    119                 FileNameMap map = java.net.URLConnection.getFileNameMap();
    120                 contentType = map.getContentTypeFor(filename);
    121                 if (contentType != null) {
    122                     properties.add(CONTENT_TYPE, contentType);
    123                 }
    124                 properties.add(CONTENT_LENGTH, String.valueOf(length));
    125 
    126                 /*
    127                  * Format the last-modified field into the preferred
    128                  * Internet standard - ie: fixed-length subset of that
    129                  * defined by RFC 1123
    130                  */
    131                 if (lastModified != 0) {
    132                     Date date = new Date(lastModified);
    133                     SimpleDateFormat fo =
    134                         new SimpleDateFormat ("EEE, dd MMM yyyy HH:mm:ss 'GMT'", 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         if (length > Integer.MAX_VALUE)
    158             return -1;
    159         return (int) length;
    160     }
    161 
    162     public long getContentLengthLong() {
    163         initializeHeaders();
    164         return length;
    165     }
    166 
    167     public String getHeaderFieldKey(int n) {
    168         initializeHeaders();
    169         return super.getHeaderFieldKey(n);
    170     }
    171 
    172     public MessageHeader getProperties() {
    173         initializeHeaders();
    174         return super.getProperties();
    175     }
    176 
    177     public long getLastModified() {
    178         initializeHeaders();
    179         return lastModified;
    180     }
    181 
    182     public synchronized InputStream getInputStream()
    183         throws IOException {
    184 
    185         int iconHeight;
    186         int iconWidth;
    187 
    188         connect();
    189 
    190         if (is == null) {
    191             if (isDirectory) {
    192                 FileNameMap map = java.net.URLConnection.getFileNameMap();
    193 
    194                 StringBuffer buf = new StringBuffer();
    195 
    196                 if (files == null) {
    197                     throw new FileNotFoundException(filename);
    198                 }
    199 
    200                 Collections.sort(files, Collator.getInstance());
    201 
    202                 for (int i = 0 ; i < files.size() ; i++) {
    203                     String fileName = files.get(i);
    204                     buf.append(fileName);
    205                     buf.append("\n");
    206                 }
    207                 // Put it into a (default) locale-specific byte-stream.
    208                 is = new ByteArrayInputStream(buf.toString().getBytes());
    209             } else {
    210                 throw new FileNotFoundException(filename);
    211             }
    212         }
    213         return is;
    214     }
    215 
    216     Permission permission;
    217 
    218     /* since getOutputStream isn't supported, only read permission is
    219      * relevant
    220      */
    221     public Permission getPermission() throws IOException {
    222         if (permission == null) {
    223             String decodedPath = ParseUtil.decode(url.getPath());
    224             if (File.separatorChar == '/') {
    225                 permission = new FilePermission(decodedPath, "read");
    226             } else {
    227                 permission = new FilePermission(
    228                         decodedPath.replace('/',File.separatorChar), "read");
    229             }
    230         }
    231         return permission;
    232     }
    233 }
    234