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