File.java revision e32b21f14d52bac429a9c54fe031f9e92c911d64
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18070f14c41b2494fd008afc4d96b873873692945fElliott Hughes// BEGIN android-note
19070f14c41b2494fd008afc4d96b873873692945fElliott Hughes// We've dropped Windows support, except where it's exposed: we still support
20070f14c41b2494fd008afc4d96b873873692945fElliott Hughes// non-Unix separators in serialized File objects, for example, but we don't
21070f14c41b2494fd008afc4d96b873873692945fElliott Hughes// have any code for UNC paths or case-insensitivity.
22070f14c41b2494fd008afc4d96b873873692945fElliott Hughes// We've also changed the JNI interface to better match what the Java actually wants.
23070f14c41b2494fd008afc4d96b873873692945fElliott Hughes// (The JNI implementation is also much simpler.)
24070f14c41b2494fd008afc4d96b873873692945fElliott Hughes// Some methods have been rewritten to reduce unnecessary allocation.
25070f14c41b2494fd008afc4d96b873873692945fElliott Hughes// Some duplication has been factored out.
26070f14c41b2494fd008afc4d96b873873692945fElliott Hughes// END android-note
27070f14c41b2494fd008afc4d96b873873692945fElliott Hughes
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.io;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URI;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URISyntaxException;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URL;
3393a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughesimport java.nio.ByteBuffer;
3493a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughesimport java.nio.charset.Charset;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.AccessController;
36f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilsonimport java.security.SecureRandom;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List;
39f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilsonimport org.apache.harmony.luni.util.DeleteOnExit;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.luni.util.PriviAction;
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * An "abstract" representation of a file system entity identified by a
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * pathname. The pathname may be absolute (relative to the root directory
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of the file system) or relative to the current directory in which the program
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * is running.
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
480af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * The actual file referenced by a {@code File} may or may not exist. It may
490af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * also, despite the name {@code File}, be a directory or other non-regular
500af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * file.
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
520af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * This class provides limited functionality for getting/setting file
530af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * permissions, file type, and last modified time.
540af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * <p>
550af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * Although Java doesn't specify a character encoding for filenames, on Android
560af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * Java strings are converted to UTF-8 byte sequences when sending filenames to
570af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * the operating system, and byte sequences returned by the operating system
580af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * (from the various {@code list} methods) are converted to Java strings by
590af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes * decoding them as UTF-8 byte sequences.
60f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.Serializable
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.lang.Comparable
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class File implements Serializable, Comparable<File> {
65f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = 301077366599181567L;
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
68c903e6720bbbf6540c29f141bd2fa559813ea20aElliott Hughes    private static final Charset UTF_8 = Charset.forName("UTF-8");
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
71f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * The system dependent file separator character.
72070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * This field is initialized from the system property "file.separator".
73070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * Later changes to that property will have no effect on this field or this class.
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final char separatorChar;
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
78070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * The system dependent file separator string.
79070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * This field is a single-character string equal to String.valueOf(separatorChar).
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final String separator;
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
84f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * The system dependent path separator character.
85070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * This field is initialized from the system property "path.separator".
86070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * Later changes to that property will have no effect on this field or this class.
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final char pathSeparatorChar;
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
91070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * The system dependent path separator string.
92070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * This field is a single-character string equal to String.valueOf(pathSeparatorChar).
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final String pathSeparator;
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /* Temp file counter */
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static int counter;
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
99070f14c41b2494fd008afc4d96b873873692945fElliott Hughes    /**
100070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * The path we return from getPath. This is almost the path we were
101070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * given, but without duplicate adjacent slashes and without trailing
102070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * slashes (except for the special case of the root directory). This
103070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * path may be the empty string.
104070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     */
105070f14c41b2494fd008afc4d96b873873692945fElliott Hughes    private String path;
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
107070f14c41b2494fd008afc4d96b873873692945fElliott Hughes    /**
108070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * The cached UTF-8 byte sequence corresponding to 'path'.
109070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * This is suitable for direct use by our JNI, and includes a trailing NUL.
110070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * For non-absolute paths, the "user.dir" property is prepended: that is,
111070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * this byte sequence usually represents an absolute path (the exception
112070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * being if the user overwrites the "user.dir" property with a non-absolute
113070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     * path).
114070f14c41b2494fd008afc4d96b873873692945fElliott Hughes     */
115070f14c41b2494fd008afc4d96b873873692945fElliott Hughes    transient byte[] pathBytes;
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static {
118070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        // The default protection domain grants access to these properties.
119f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        separatorChar = System.getProperty("file.separator", "/").charAt(0);
120f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        pathSeparatorChar = System.getProperty("path.separator", ":").charAt(0);
121070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        separator = String.valueOf(separatorChar);
122070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        pathSeparator = String.valueOf(pathSeparatorChar);
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new file using the specified directory and name.
127f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dir
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the directory where the file is stored.
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the file's name.
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
133f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *             if {@code name} is {@code null}.
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public File(File dir, String name) {
13693a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        this(dir == null ? null : dir.getPath(), name);
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new file using the specified path.
141f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param path
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the path to be used for the file.
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public File(String path) {
146070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        init(path);
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new File using the specified directory path and file name,
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * placing a path separator between the two.
152f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param dirPath
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the path to the directory where the file is stored.
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the file's name.
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
158f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *             if {@code name} is {@code null}.
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public File(String dirPath, String name) {
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (name == null) {
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new NullPointerException();
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
164ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (dirPath == null || dirPath.isEmpty()) {
165070f14c41b2494fd008afc4d96b873873692945fElliott Hughes            init(name);
166ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        } else if (name.isEmpty()) {
167070f14c41b2494fd008afc4d96b873873692945fElliott Hughes            init(dirPath);
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
169070f14c41b2494fd008afc4d96b873873692945fElliott Hughes            init(join(dirPath, name));
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new File using the path of the specified URI. {@code uri}
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * needs to be an absolute and hierarchical Unified Resource Identifier with
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * file scheme and non-empty path component, but with undefined authority,
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * query or fragment components.
178f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param uri
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the Unified Resource Identifier that is used to construct this
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            file.
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code uri} does not comply with the conditions above.
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #toURI
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see java.net.URI
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public File(URI uri) {
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // check pre-conditions
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkURI(uri);
190070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        init(uri.getPath());
19193a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes    }
19293a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes
193070f14c41b2494fd008afc4d96b873873692945fElliott Hughes    private void init(String dirtyPath) {
194070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        // Keep a copy of the cleaned-up string path.
195070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        this.path = fixSlashes(dirtyPath);
19693a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        // Cache the UTF-8 bytes we need for the JNI.
197028794d8a42840233d3cb316feb09b5593f19d1dElliott Hughes        // TODO: we shouldn't do this caching at all; the RI demonstrably doesn't.
198028794d8a42840233d3cb316feb09b5593f19d1dElliott Hughes        if (path.length() > 0 && path.charAt(0) == separatorChar) { // http://b/2486943
19993a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes            this.pathBytes = newCString(path);
20093a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes            return;
20193a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        }
20293a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        String userDir = AccessController.doPrivileged(
203f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            new PriviAction<String>("user.dir"));
204ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        this.pathBytes = newCString(path.isEmpty() ? userDir : join(userDir, path));
20593a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes    }
20693a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes
20793a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes    private byte[] newCString(String s) {
208c903e6720bbbf6540c29f141bd2fa559813ea20aElliott Hughes        ByteBuffer buffer = UTF_8.encode(s);
20993a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        // Add a trailing NUL, because this byte[] is going to be used as a char*.
21093a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        int byteCount = buffer.limit() + 1;
21193a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        byte[] bytes = new byte[byteCount];
21293a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        buffer.get(bytes, 0, byteCount - 1);
21393a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        // This is an awful mistake, because '\' is a perfectly acceptable
21493a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        // character on Linux/Android. But we've shipped so many versions
21593a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        // that behaved like this, I'm too scared to change it.
21693a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        for (int i = 0; i < bytes.length; ++i) {
21793a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes            if (bytes[i] == '\\') {
21893a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes                bytes[i] = '/';
21993a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes            }
22093a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        }
22193a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        return bytes;
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
224070f14c41b2494fd008afc4d96b873873692945fElliott Hughes    // Removes duplicate adjacent slashes and any trailing slash.
225070f14c41b2494fd008afc4d96b873873692945fElliott Hughes    private String fixSlashes(String origPath) {
226070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        // Remove duplicate adjacent slashes.
227070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        boolean lastWasSlash = false;
228070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        char[] newPath = origPath.toCharArray();
229070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        int length = newPath.length;
230070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        int newLength = 0;
231070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        for (int i = 0; i < length; ++i) {
232070f14c41b2494fd008afc4d96b873873692945fElliott Hughes            char ch = newPath[i];
233070f14c41b2494fd008afc4d96b873873692945fElliott Hughes            if (ch == '/') {
234070f14c41b2494fd008afc4d96b873873692945fElliott Hughes                if (!lastWasSlash) {
235070f14c41b2494fd008afc4d96b873873692945fElliott Hughes                    newPath[newLength++] = separatorChar;
236070f14c41b2494fd008afc4d96b873873692945fElliott Hughes                    lastWasSlash = true;
237070f14c41b2494fd008afc4d96b873873692945fElliott Hughes                }
238070f14c41b2494fd008afc4d96b873873692945fElliott Hughes            } else {
239070f14c41b2494fd008afc4d96b873873692945fElliott Hughes                newPath[newLength++] = ch;
240070f14c41b2494fd008afc4d96b873873692945fElliott Hughes                lastWasSlash = false;
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
243070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        // Remove any trailing slash (unless this is the root of the file system).
244070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        if (lastWasSlash && newLength > 1) {
245070f14c41b2494fd008afc4d96b873873692945fElliott Hughes            newLength--;
246070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        }
247070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        // Reuse the original string if possible.
248070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        return (newLength != length) ? new String(newPath, 0, newLength) : origPath;
249070f14c41b2494fd008afc4d96b873873692945fElliott Hughes    }
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
251070f14c41b2494fd008afc4d96b873873692945fElliott Hughes    // Joins two path components, adding a separator only if necessary.
252070f14c41b2494fd008afc4d96b873873692945fElliott Hughes    private String join(String prefix, String suffix) {
253070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        int prefixLength = prefix.length();
254070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        boolean haveSlash = (prefixLength > 0 && prefix.charAt(prefixLength - 1) == separatorChar);
255070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        if (!haveSlash) {
256070f14c41b2494fd008afc4d96b873873692945fElliott Hughes            haveSlash = (suffix.length() > 0 && suffix.charAt(0) == separatorChar);
257070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        }
258070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        return haveSlash ? (prefix + suffix) : (prefix + separatorChar + suffix);
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void checkURI(URI uri) {
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!uri.isAbsolute()) {
263b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("URI is not absolute: " + uri);
264f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) {
265b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("URI is not hierarchical: " + uri);
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
267e32b21f14d52bac429a9c54fe031f9e92c911d64Jesse Wilson        if (!"file".equals(uri.getScheme())) {
268b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("Expected file scheme in URI: " + uri);
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
270e32b21f14d52bac429a9c54fe031f9e92c911d64Jesse Wilson        String rawPath = uri.getRawPath();
271e32b21f14d52bac429a9c54fe031f9e92c911d64Jesse Wilson        if (rawPath == null || rawPath.isEmpty()) {
272b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("Expected non-empty path in URI: " + uri);
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (uri.getRawAuthority() != null) {
275b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("Found authority in URI: " + uri);
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (uri.getRawQuery() != null) {
278b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("Found query in URI: " + uri);
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (uri.getRawFragment() != null) {
281b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("Found fragment in URI: " + uri);
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Lists the file system roots. The Java platform may support zero or more
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * file systems, each with its own platform-dependent root. Further, the
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * canonical pathname of any file on the system will always begin with one
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of the returned file system roots.
290f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the array of file system roots.
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static File[] listRoots() {
29487415b1521402398d4470aecbef7c126a6948290Elliott Hughes        return new File[] { new File("/") };
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
29808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Tests whether or not this process is allowed to execute this file.
29908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Note that this is a best-effort result; the only way to be certain is
30008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * to actually attempt the operation.
30108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *
30208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @return {@code true} if this file can be executed, {@code false} otherwise.
30308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @throws SecurityException
30408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             If a security manager exists and
30508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             SecurityManager.checkExec(java.lang.String) disallows read
30608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             permission to this file object
30708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @see java.lang.SecurityManager#checkExec(String)
30808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *
30908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @since 1.6
31008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     */
31108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    public boolean canExecute() {
312ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
31308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes            return false;
31408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        }
31508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        SecurityManager security = System.getSecurityManager();
31608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        if (security != null) {
31708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes            security.checkExec(path); // Seems bogus, but this is what the RI does.
31808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        }
31908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return canExecuteImpl(pathBytes);
32008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    }
32108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    private native boolean canExecuteImpl(byte[] filePath);
32208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
32308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    /**
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether the current context is allowed to read from this file.
325f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this file can be read, {@code false} otherwise.
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies the
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             read request.
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean canRead() {
332ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
333f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            return false;
334f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        }
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkRead(path);
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
33908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return canReadImpl(pathBytes);
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
34108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    private native boolean canReadImpl(byte[] filePath);
3420af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether the current context is allowed to write to this file.
345f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this file can be written, {@code false}
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise.
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies the
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             write request.
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean canWrite() {
353ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
354c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes            return false;
355c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes        }
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkWrite(path);
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
36008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return canWriteImpl(pathBytes);
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
36208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    private native boolean canWriteImpl(byte[] filePath);
3630af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the relative sort ordering of the paths for this file and the
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * file {@code another}. The ordering is platform dependent.
367f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param another
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a file to compare this file to
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an int determined by comparing the two paths. Possible values are
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         described in the Comparable interface.
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see Comparable
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int compareTo(File another) {
375070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        return this.getPath().compareTo(another.getPath());
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Deletes this file. Directories must be empty before they will be deleted.
380f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
381ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
382ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * Callers must check the return value.
383ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     *
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this file was deleted, {@code false} otherwise.
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies the
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             request.
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see java.lang.SecurityManager#checkDelete
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean delete() {
391ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
392c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes            return false;
393c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes        }
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkDelete(path);
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
39893a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        return deleteImpl(pathBytes);
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
401c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes    private native boolean deleteImpl(byte[] filePath);
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Schedules this file to be automatically deleted once the virtual machine
405f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * terminates. This will only happen when the virtual machine terminates
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * normally as described by the Java Language Specification section 12.9.
407f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies the
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             request.
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void deleteOnExit() {
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkDelete(path);
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        DeleteOnExit.getInstance().addFile(getAbsoluteName());
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Compares {@code obj} to this file and returns {@code true} if they
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * represent the <em>same</em> object using a path specific comparison.
423f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param obj
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the object to compare this file with.
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if {@code obj} is the same as this object,
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code false} otherwise.
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean equals(Object obj) {
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!(obj instanceof File)) {
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return path.equals(((File) obj).getPath());
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a boolean indicating whether this file can be found on the
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * underlying file system.
440f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this file exists, {@code false} otherwise.
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies read
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access to this file.
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #getPath
446f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean exists() {
449ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkRead(path);
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
45693a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        return existsImpl(pathBytes);
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private native boolean existsImpl(byte[] filePath);
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the absolute path of this file.
463f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the absolute file path.
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getAbsolutePath() {
467c903e6720bbbf6540c29f141bd2fa559813ea20aElliott Hughes        return new String(pathBytes, 0, pathBytes.length - 1, UTF_8);
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a new file constructed using the absolute path of this file.
472f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a new file from this file's absolute path.
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see java.lang.SecurityManager#checkPropertyAccess
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public File getAbsoluteFile() {
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new File(this.getAbsolutePath());
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the absolute path of this file with all references resolved. An
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <em>absolute</em> path is one that begins at the root of the file
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * system. The canonical path is one in which all references have been
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * resolved. For the cases of '..' and '.', where the file system supports
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * parent and working directory respectively, these are removed and replaced
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * with a direct directory reference. If the file does not exist,
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * getCanonicalPath() may not resolve any references and simply returns an
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * absolute path name or throws an IOException.
489f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the canonical path of this file.
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an I/O error occurs.
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getCanonicalPath() throws IOException {
4954030ad60f305d1f23e9b681dca7a181ab4f09276Jesse Wilson        // BEGIN android-removed
4961072631d16a5e5ffd97ae346e20dcd112df9dc13Jesse Wilson        //     Caching the canonical path is bogus. Users facing specific
4971072631d16a5e5ffd97ae346e20dcd112df9dc13Jesse Wilson        //     performance problems can perform their own caching, with
4981072631d16a5e5ffd97ae346e20dcd112df9dc13Jesse Wilson        //     eviction strategies that are appropriate for their application.
4991072631d16a5e5ffd97ae346e20dcd112df9dc13Jesse Wilson        //     A VM-wide cache with no mechanism to evict stale elements is a
5001072631d16a5e5ffd97ae346e20dcd112df9dc13Jesse Wilson        //     disservice to applications that need up-to-date data.
5014030ad60f305d1f23e9b681dca7a181ab4f09276Jesse Wilson        // String canonPath = FileCanonPathCache.get(absPath);
5024030ad60f305d1f23e9b681dca7a181ab4f09276Jesse Wilson        // if (canonPath != null) {
5034030ad60f305d1f23e9b681dca7a181ab4f09276Jesse Wilson        //     return canonPath;
5044030ad60f305d1f23e9b681dca7a181ab4f09276Jesse Wilson        // }
5054030ad60f305d1f23e9b681dca7a181ab4f09276Jesse Wilson        // END android-removed
5064030ad60f305d1f23e9b681dca7a181ab4f09276Jesse Wilson
50793a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        byte[] result = pathBytes;
508f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if(separatorChar == '/') {
509f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            // resolve the full path first
510f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            result = resolveLink(result, result.length, false);
511f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            // resolve the parent directories
512f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            result = resolve(result);
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int numSeparators = 1;
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i < result.length; i++) {
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (result[i] == separatorChar) {
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                numSeparators++;
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int sepLocations[] = new int[numSeparators];
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int rootLoc = 0;
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (separatorChar != '/') {
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (result[0] == '\\') {
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                rootLoc = (result.length > 1 && result[1] == '\\') ? 1 : 0;
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                rootLoc = 2; // skip drive i.e. c:
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte newResult[] = new byte[result.length + 1];
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int newLength = 0, lastSlash = 0, foundDots = 0;
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sepLocations[lastSlash] = rootLoc;
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i <= result.length; i++) {
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (i < rootLoc) {
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                newResult[newLength++] = result[i];
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (i == result.length || result[i] == separatorChar) {
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (i == result.length && foundDots == 0) {
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        break;
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (foundDots == 1) {
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        /* Don't write anything, just reset and continue */
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        foundDots = 0;
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        continue;
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (foundDots > 1) {
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        /* Go back N levels */
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        lastSlash = lastSlash > (foundDots - 1) ? lastSlash
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                - (foundDots - 1) : 0;
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        newLength = sepLocations[lastSlash] + 1;
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        foundDots = 0;
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        continue;
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    sepLocations[++lastSlash] = newLength;
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    newResult[newLength++] = (byte) separatorChar;
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    continue;
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (result[i] == '.') {
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    foundDots++;
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    continue;
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                /* Found some dots within text, write them out */
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (foundDots > 0) {
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    for (int j = 0; j < foundDots; j++) {
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        newResult[newLength++] = (byte) '.';
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                newResult[newLength++] = result[i];
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                foundDots = 0;
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // remove trailing slash
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (newLength > (rootLoc + 1)
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && newResult[newLength - 1] == separatorChar) {
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            newLength--;
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        newResult[newLength] = 0;
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        newResult = getCanonImpl(newResult);
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        newLength = newResult.length;
579c903e6720bbbf6540c29f141bd2fa559813ea20aElliott Hughes        return new String(newResult, 0, newLength, UTF_8);
580f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
581f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
582f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    /*
583f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Resolve symbolic links in the parent directories.
584f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     */
585f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private byte[] resolve(byte[] newResult) throws IOException {
586f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        int last = 1, nextSize, linkSize;
587f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        byte[] linkPath = newResult, bytes;
588f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        boolean done, inPlace;
589f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        for (int i = 1; i <= newResult.length; i++) {
590f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (i == newResult.length || newResult[i] == separatorChar) {
591f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                done = i >= newResult.length - 1;
592f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                // if there is only one segment, do nothing
593f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (done && linkPath.length == 1) {
594f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    return newResult;
595f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                }
596f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                inPlace = false;
597f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (linkPath == newResult) {
598f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    bytes = newResult;
599f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    // if there are no symbolic links, terminate the C string
600f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    // instead of copying
601f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    if (!done) {
602f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                        inPlace = true;
603f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                        newResult[i] = '\0';
604f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    }
605f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                } else {
606f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    nextSize = i - last + 1;
607f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    linkSize = linkPath.length;
608f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    if (linkPath[linkSize - 1] == separatorChar) {
609f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                        linkSize--;
610f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    }
611f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    bytes = new byte[linkSize + nextSize];
612f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    System.arraycopy(linkPath, 0, bytes, 0, linkSize);
613f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    System.arraycopy(newResult, last - 1, bytes, linkSize,
614f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                            nextSize);
615f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    // the full path has already been resolved
616f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                }
617f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (done) {
618f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    return bytes;
619f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                }
620f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                linkPath = resolveLink(bytes, inPlace ? i : bytes.length, true);
621f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                if (inPlace) {
622f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    newResult[i] = '/';
623f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                }
624f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                last = i + 1;
625f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
626f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        }
627f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        throw new InternalError();
628f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    }
629f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson
630f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    /*
631f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Resolve a symbolic link. While the path resolves to an existing path,
632f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * keep resolving. If an absolute link is found, resolve the parent
633f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * directories if resolveAbsolute is true.
634f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     */
635f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    private byte[] resolveLink(byte[] pathBytes, int length,
636f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            boolean resolveAbsolute) throws IOException {
637f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        boolean restart = false;
638f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        byte[] linkBytes, temp;
639f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        do {
640f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            linkBytes = getLinkImpl(pathBytes);
641f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (linkBytes == pathBytes) {
642f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                break;
643f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
644f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (linkBytes[0] == separatorChar) {
645f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                // link to an absolute path, if resolving absolute paths,
646f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                // resolve the parent dirs again
647f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                restart = resolveAbsolute;
648f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                pathBytes = linkBytes;
649f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else {
650f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                int last = length - 1;
651f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                while (pathBytes[last] != separatorChar) {
652f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                    last--;
653f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                }
654f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                last++;
655f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                temp = new byte[last + linkBytes.length];
656f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                System.arraycopy(pathBytes, 0, temp, 0, last);
657f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                System.arraycopy(linkBytes, 0, temp, last, linkBytes.length);
658f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                pathBytes = temp;
659f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            }
660f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            length = pathBytes.length;
661f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        } while (existsImpl(pathBytes));
662f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        // resolve the parent directories
663f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if (restart) {
664f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            return resolve(pathBytes);
665f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        }
666f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        return pathBytes;
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
6690af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes    private native byte[] getLinkImpl(byte[] filePath);
6700af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a new file created using the canonical path of this file.
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Equivalent to {@code new File(this.getCanonicalPath())}.
674f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the new file constructed from this file's canonical path.
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an I/O error occurs.
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see java.lang.SecurityManager#checkPropertyAccess
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public File getCanonicalFile() throws IOException {
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new File(getCanonicalPath());
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private native byte[] getCanonImpl(byte[] filePath);
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the name of the file or directory represented by this file.
688f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this file's name or an empty string if there is no name part in
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         the file's path.
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getName() {
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int separatorIndex = path.lastIndexOf(separator);
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1,
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                path.length());
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the pathname of the parent of this file. This is the path up to
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * but not including the last name. {@code null} is returned if there is no
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * parent.
702f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this file's parent pathname or {@code null}.
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getParent() {
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int length = path.length(), firstInPath = 0;
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (separatorChar == '\\' && length > 2 && path.charAt(1) == ':') {
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            firstInPath = 2;
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int index = path.lastIndexOf(separatorChar);
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (index == -1 && firstInPath > 0) {
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            index = 2;
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (index == -1 || path.charAt(length - 1) == separatorChar) {
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (path.indexOf(separatorChar) == index
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && path.charAt(firstInPath) == separatorChar) {
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return path.substring(0, index + 1);
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return path.substring(0, index);
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a new file made from the pathname of the parent of this file.
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This is the path up to but not including the last name. {@code null} is
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * returned when there is no parent.
728f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a new file representing this file's parent or {@code null}.
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public File getParentFile() {
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String tempParent = getParent();
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (tempParent == null) {
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new File(tempParent);
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the path of this file.
741f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this file's path.
743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String getPath() {
745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return path;
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an integer hash code for the receiver. Any two objects for which
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code equals} returns {@code true} must return the same hash code.
751f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this files's hash value.
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #equals
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int hashCode() {
757070f14c41b2494fd008afc4d96b873873692945fElliott Hughes        return getPath().hashCode() ^ 1234321;
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates if this file's pathname is absolute. Whether a pathname is
7620af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * absolute is platform specific. On Android, absolute paths start with
7630af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * the character '/'.
76408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this file's pathname is absolute, {@code false}
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise.
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #getPath
768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isAbsolute() {
770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return path.length() > 0 && path.charAt(0) == separatorChar;
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates if this file represents a <em>directory</em> on the
775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * underlying file system.
776f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this file is a directory, {@code false}
778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise.
779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies read
781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access to this file.
782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isDirectory() {
784ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkRead(path);
790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
79193a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        return isDirectoryImpl(pathBytes);
792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private native boolean isDirectoryImpl(byte[] filePath);
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates if this file represents a <em>file</em> on the underlying
798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * file system.
799f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this file is a file, {@code false} otherwise.
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies read
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access to this file.
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isFile() {
806ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkRead(path);
812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
81393a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        return isFileImpl(pathBytes);
814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private native boolean isFileImpl(byte[] filePath);
817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns whether or not this file is a hidden file as defined by the
820f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * operating system. The notion of "hidden" is system-dependent. For Unix
821f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * systems a file is considered hidden if its name starts with a ".". For
822f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * Windows systems there is an explicit flag in the file system for this
823f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * purpose.
824f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the file is hidden, {@code false} otherwise.
826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies read
828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access to this file.
829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isHidden() {
831ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkRead(path);
837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
83887415b1521402398d4470aecbef7c126a6948290Elliott Hughes        return getName().startsWith(".");
839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the time when this file was last modified, measured in
843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * milliseconds since January 1st, 1970, midnight.
8441326cfc6f105f6c8fd5ffd83793223e1a797409dElliott Hughes     * Returns 0 if the file does not exist.
845f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the time when this file was last modified.
847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies read
849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access to this file.
850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public long lastModified() {
852ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
853c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes            return 0;
854c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes        }
855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkRead(path);
858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
85993a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        return lastModifiedImpl(pathBytes);
860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private native long lastModifiedImpl(byte[] filePath);
863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the time this file was last modified, measured in milliseconds since
866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * January 1st, 1970, midnight.
867f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
868ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
869ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * Callers must check the return value.
870ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     *
871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param time
872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the last modification time for this file.
873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the operation is successful, {@code false}
874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise.
875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code time < 0}.
877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies write
879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access to this file.
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean setLastModified(long time) {
882ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
883c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes            return false;
884c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes        }
885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (time < 0) {
886b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("time < 0");
887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkWrite(path);
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
89293a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        return setLastModifiedImpl(pathBytes, time);
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private native boolean setLastModifiedImpl(byte[] path, long time);
896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
89808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Equivalent to setWritable(false, false).
899f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
90008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @see #setWritable(boolean, boolean)
901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean setReadOnly() {
90308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return setWritable(false, false);
90408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    }
90508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
90608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    /**
90708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Manipulates the execute permissions for the abstract path designated by
90808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * this file.
90908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *
910ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
911ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * Callers must check the return value.
912ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     *
91308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @param executable
91408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            To allow execute permission if true, otherwise disallow
91508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @param ownerOnly
91608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            To manipulate execute permission only for owner if true,
91708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            otherwise for everyone. The manipulation will apply to
91808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            everyone regardless of this value if the underlying system
91908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            does not distinguish owner and other users.
92008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @return true if and only if the operation succeeded. If the user does not
92108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *         have permission to change the access permissions of this abstract
92208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *         pathname the operation will fail. If the underlying file system
92308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *         does not support execute permission and the value of executable
92408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *         is false, this operation will fail.
92508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @throws SecurityException -
92608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             If a security manager exists and
92708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             SecurityManager.checkWrite(java.lang.String) disallows write
92808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             permission to this file object
92908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @since 1.6
93008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     */
93108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    public boolean setExecutable(boolean executable, boolean ownerOnly) {
932ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
933c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes            return false;
934c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes        }
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkWrite(path);
938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
93908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return setExecutableImpl(pathBytes, executable, ownerOnly);
94008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    }
94108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
94208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    /**
94308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Equivalent to setExecutable(executable, true).
944ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * @see #setExecutable(boolean, boolean)
94508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @since 1.6
94608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     */
94708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    public boolean setExecutable(boolean executable) {
94808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return setExecutable(executable, true);
949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
95108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    private native boolean setExecutableImpl(byte[] path, boolean executable, boolean ownerOnly);
95208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
95308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    /**
95408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Manipulates the read permissions for the abstract path designated by this
95508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * file.
95608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *
95708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @param readable
95808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            To allow read permission if true, otherwise disallow
95908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @param ownerOnly
96008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            To manipulate read permission only for owner if true,
96108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            otherwise for everyone. The manipulation will apply to
96208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            everyone regardless of this value if the underlying system
96308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            does not distinguish owner and other users.
96408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @return true if and only if the operation succeeded. If the user does not
96508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *         have permission to change the access permissions of this abstract
96608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *         pathname the operation will fail. If the underlying file system
96708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *         does not support read permission and the value of readable is
96808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *         false, this operation will fail.
96908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @throws SecurityException -
97008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             If a security manager exists and
97108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             SecurityManager.checkWrite(java.lang.String) disallows write
97208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             permission to this file object
97308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @since 1.6
97408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     */
97508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    public boolean setReadable(boolean readable, boolean ownerOnly) {
976ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
97708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes            return false;
97808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        }
97908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        SecurityManager security = System.getSecurityManager();
98008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        if (security != null) {
98108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes            security.checkWrite(path);
98208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        }
98308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return setReadableImpl(pathBytes, readable, ownerOnly);
98408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    }
98508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
98608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    /**
98708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Equivalent to setReadable(readable, true).
988ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * @see #setReadable(boolean, boolean)
98908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @since 1.6
99008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     */
99108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    public boolean setReadable(boolean readable) {
99208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return setReadable(readable, true);
99308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    }
99408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
99508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    private native boolean setReadableImpl(byte[] path, boolean readable, boolean ownerOnly);
99608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
99708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    /**
99808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Manipulates the write permissions for the abstract path designated by this
99908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * file.
100008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *
100108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @param writable
100208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            To allow write permission if true, otherwise disallow
100308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @param ownerOnly
100408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            To manipulate write permission only for owner if true,
100508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            otherwise for everyone. The manipulation will apply to
100608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            everyone regardless of this value if the underlying system
100708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *            does not distinguish owner and other users.
100808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @return true if and only if the operation succeeded. If the user does not
100908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *         have permission to change the access permissions of this abstract
101008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *         pathname the operation will fail.
101108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @throws SecurityException -
101208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             If a security manager exists and
101308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             SecurityManager.checkWrite(java.lang.String) disallows write
101408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *             permission to this file object
101508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @since 1.6
101608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     */
101708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    public boolean setWritable(boolean writable, boolean ownerOnly) {
1018ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
101908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes            return false;
102008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        }
102108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        SecurityManager security = System.getSecurityManager();
102208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        if (security != null) {
102308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes            security.checkWrite(path);
102408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        }
102508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return setWritableImpl(pathBytes, writable, ownerOnly);
102608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    }
102708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
102808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    /**
102908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Equivalent to setWritable(writable, true).
1030ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * @see #setWritable(boolean, boolean)
103108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @since 1.6
103208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     */
103308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    public boolean setWritable(boolean writable) {
103408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return setWritable(writable, true);
103508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    }
103608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
103708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    private native boolean setWritableImpl(byte[] path, boolean writable, boolean ownerOnly);
1038adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1039adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1040adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the length of this file in bytes.
10411326cfc6f105f6c8fd5ffd83793223e1a797409dElliott Hughes     * Returns 0 if the file does not exist.
10421326cfc6f105f6c8fd5ffd83793223e1a797409dElliott Hughes     * The result for a directory is not defined.
1043f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1044adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of bytes in this file.
1045adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
1046adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies read
1047adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access to this file.
1048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1049adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public long length() {
1050adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
1051adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
1052adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkRead(path);
1053adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
105493a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        return lengthImpl(pathBytes);
1055adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1056adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1057adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private native long lengthImpl(byte[] filePath);
1058adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1060adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an array of strings with the file names in the directory
1061f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * represented by this file. The result is {@code null} if this file is not
1062f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * a directory.
1063adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1064adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The entries {@code .} and {@code ..} representing the current and parent
1065adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * directory are not returned as part of the list.
1066f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1067adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of strings with file names or {@code null}.
1068adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
1069adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies read
1070adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access to this file.
1071adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #isDirectory
1072f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
1073adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
10740af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes    public String[] list() {
1075adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
1076adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
1077adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkRead(path);
1078adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1079ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
1080adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
1081adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1082f226fd4060db45a0738cbbc1bb49bebe5963ac11Elliott Hughes        return listImpl(pathBytes);
1083adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1084adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1085f226fd4060db45a0738cbbc1bb49bebe5963ac11Elliott Hughes    private native String[] listImpl(byte[] path);
10860af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes
10870af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes    /**
10880af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * Gets a list of the files in the directory represented by this file. This
10890af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * list is then filtered through a FilenameFilter and the names of files
10900af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * with matching names are returned as an array of strings. Returns
10910af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * {@code null} if this file is not a directory. If {@code filter} is
10920af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * {@code null} then all filenames match.
10930af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * <p>
10940af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * The entries {@code .} and {@code ..} representing the current and parent
10950af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * directories are not returned as part of the list.
10960af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     *
10970af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * @param filter
10980af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     *            the filter to match names against, may be {@code null}.
10990af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * @return an array of files or {@code null}.
11000af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * @throws SecurityException
11010af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     *             if a {@code SecurityManager} is installed and it denies read
11020af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     *             access to this file.
11030af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * @see #getPath
11040af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * @see #isDirectory
11050af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
11060af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     */
11070af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes    public String[] list(FilenameFilter filter) {
11080af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        String[] filenames = list();
11090af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        if (filter == null || filenames == null) {
11100af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes            return filenames;
11110af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        }
11120af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        List<String> result = new ArrayList<String>(filenames.length);
11130af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        for (String filename : filenames) {
11140af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes            if (filter.accept(this, filename)) {
11150af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes                result.add(filename);
11160af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes            }
11170af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        }
11180af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        return result.toArray(new String[result.size()]);
11190af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes    }
11200af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes
1121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an array of files contained in the directory represented by this
1123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * file. The result is {@code null} if this file is not a directory. The
1124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * paths of the files in the array are absolute if the path of this file is
1125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * absolute, they are relative otherwise.
1126f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of files or {@code null}.
1128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
1129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies read
1130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access to this file.
1131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #list
1132f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see #isDirectory
1133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public File[] listFiles() {
11350af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        return filenamesToFiles(list());
1136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets a list of the files in the directory represented by this file. This
1140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * list is then filtered through a FilenameFilter and files with matching
1141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * names are returned as an array of files. Returns {@code null} if this
1142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * file is not a directory. If {@code filter} is {@code null} then all
1143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * filenames match.
1144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The entries {@code .} and {@code ..} representing the current and parent
1146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * directories are not returned as part of the list.
1147f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param filter
1149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the filter to match names against, may be {@code null}.
1150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of files or {@code null}.
1151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
1152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies read
1153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access to this file.
1154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #list(FilenameFilter filter)
1155f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see #getPath
1156f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see #isDirectory
1157f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
1158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public File[] listFiles(FilenameFilter filter) {
11600af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        return filenamesToFiles(list(filter));
1161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets a list of the files in the directory represented by this file. This
1165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * list is then filtered through a FileFilter and matching files are
1166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * returned as an array of files. Returns {@code null} if this file is not a
1167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * directory. If {@code filter} is {@code null} then all files match.
1168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <p>
1169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The entries {@code .} and {@code ..} representing the current and parent
1170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * directories are not returned as part of the list.
1171f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param filter
1173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the filter to match names against, may be {@code null}.
1174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of files or {@code null}.
1175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
1176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies read
1177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access to this file.
1178f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see #getPath
1179f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see #isDirectory
1180f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
1181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public File[] listFiles(FileFilter filter) {
11830af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        File[] files = listFiles();
11840af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        if (filter == null || files == null) {
11850af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes            return files;
11860af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        }
11870af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        List<File> result = new ArrayList<File>(files.length);
11880af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        for (File file : files) {
11890af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes            if (filter.accept(file)) {
11900af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes                result.add(file);
1191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
11930af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        return result.toArray(new File[result.size()]);
1194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
11970af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * Converts a String[] containing filenames to a File[].
11980af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * Note that the filenames must not contain slashes.
11990af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * This method is to remove duplication in the implementation
12000af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes     * of File.list's overloads.
1201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
12020af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes    private File[] filenamesToFiles(String[] filenames) {
12030af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        if (filenames == null) {
1204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
1205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
12060af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        int count = filenames.length;
12070af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        File[] result = new File[count];
12080af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        for (int i = 0; i < count; ++i) {
12090af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes            result[i] = new File(this, filenames[i]);
1210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
12110af4ef265f1e67edfcc5e34bcb68ee42a791beefElliott Hughes        return result;
1212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates the directory named by the trailing filename of this file. Does
1216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * not create the complete path required to create this directory.
1217f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1218ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
1219ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * Callers must check the return value.
1220ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     *
1221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the directory has been created, {@code false}
1222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise.
1223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
1224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies write
1225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access for this file.
1226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #mkdirs
1227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean mkdir() {
1229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
1230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
1231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkWrite(path);
1232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
123393a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        return mkdirImpl(pathBytes);
1234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private native boolean mkdirImpl(byte[] filePath);
1237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates the directory named by the trailing filename of this file,
1240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * including the complete directory path required to create this directory.
1241f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1242ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
1243ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * Callers must check the return value.
1244ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     *
1245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the necessary directories have been created,
1246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code false} if the target directory already exists or one of
1247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         the directories can not be created.
1248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
1249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies write
1250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access for this file.
1251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see #mkdir
1252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean mkdirs() {
1254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /* If the terminal directory already exists, answer false */
1255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (exists()) {
1256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
1257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /* If the receiver can be created, answer true */
1260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (mkdir()) {
1261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
1262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String parentDir = getParent();
1265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /* If there is no parent and we were not created, answer false */
1266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (parentDir == null) {
1267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
1268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /* Otherwise, try to create a parent directory and then this directory */
1271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (new File(parentDir).mkdirs() && mkdir());
1272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a new, empty file on the file system according to the path
1276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * information stored in this file.
1277f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1278ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
1279ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * Callers must check the return value.
1280ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     *
1281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if the file has been created, {@code false} if it
1282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         already exists.
128393a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes     * @throws IOException if it's not possible to create the file.
1284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
1285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies write
1286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access for this file.
1287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean createNewFile() throws IOException {
1289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
1290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
1291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkWrite(path);
1292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1293ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty()) {
1294b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IOException("No such file or directory");
1295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
129693a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        return createNewFileImpl(pathBytes);
1297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
129993a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes    private native boolean createNewFileImpl(byte[] filePath);
1300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates an empty temporary file using the given prefix and suffix as part
1303f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * of the file name. If suffix is {@code null}, {@code .tmp} is used. This
1304f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * method is a convenience method that calls
1305f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * {@link #createTempFile(String, String, File)} with the third argument
1306f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * being {@code null}.
1307f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param prefix
1309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the prefix to the temp file name.
1310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param suffix
1311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the suffix to the temp file name.
1312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the temporary file.
1313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
1314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs when writing the file.
1315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static File createTempFile(String prefix, String suffix)
1317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws IOException {
1318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return createTempFile(prefix, suffix, null);
1319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates an empty temporary file in the given directory using the given
1323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * prefix and suffix as part of the file name.
1324f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param prefix
1326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the prefix to the temp file name.
1327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param suffix
1328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the suffix to the temp file name.
1329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param directory
1330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the location to which the temp file is to be written, or
1331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            {@code null} for the default location for temporary files,
1332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            which is taken from the "java.io.tmpdir" system property. It
1333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            may be necessary to set this property to an existing, writable
1334f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *            directory for this method to work properly.
1335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the temporary file.
1336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
1337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the length of {@code prefix} is less than 3.
1338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
1339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs when writing the file.
1340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1341f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    @SuppressWarnings("nls")
1342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static File createTempFile(String prefix, String suffix,
1343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            File directory) throws IOException {
1344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Force a prefix null check first
1345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (prefix.length() < 3) {
1346b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes            throw new IllegalArgumentException("prefix must be at least 3 characters");
1347f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        }
1348f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        String newSuffix = suffix == null ? ".tmp" : suffix;
1349f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        File tmpDirFile;
1350f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if (directory == null) {
1351f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            String tmpDir = AccessController.doPrivileged(
1352f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                new PriviAction<String>("java.io.tmpdir", "."));
1353f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            tmpDirFile = new File(tmpDir);
1354f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        } else {
1355f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            tmpDirFile = directory;
1356f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        }
1357f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        File result;
1358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        do {
1359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            result = genTempFile(prefix, newSuffix, tmpDirFile);
1360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } while (!result.createNewFile());
1361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
1362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static File genTempFile(String prefix, String suffix, File directory) {
1365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (counter == 0) {
1366070f14c41b2494fd008afc4d96b873873692945fElliott Hughes            // TODO: this doesn't make a lot of sense. SecureRandom for the seed, but then always just add one?
1367f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            int newInt = new SecureRandom().nextInt();
1368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            counter = ((newInt / 65535) & 0xFFFF) + 0x2710;
1369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        StringBuilder newName = new StringBuilder();
1371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        newName.append(prefix);
1372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        newName.append(counter++);
1373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        newName.append(suffix);
1374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return new File(directory, newName.toString());
1375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1378ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * Renames this file to {@code dest}. This operation is supported for both
1379ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * files and directories.
1380ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     *
1381ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <p>Many failures are possible. Some of the more likely failures include:
1382ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <ul>
1383ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <li>Write permission is required on the directories containing both the source and
1384ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * destination paths.
1385ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <li>Search permission is required for all parents of both paths.
1386ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <li>Both paths be on the same mount point. On Android, applications are most likely to hit
1387ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * this restriction when attempting to copy between internal storage and an SD card.
1388ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * </ul>
1389ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     *
1390ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * <p>Note that this method does <i>not</i> throw {@code IOException} on failure.
1391ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * Callers must check the return value.
1392f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1393ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * @param dest the new name.
1394ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes     * @return true on success.
1395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SecurityException
1396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a {@code SecurityManager} is installed and it denies write
1397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             access for this file or the {@code dest} file.
1398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1399ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes    public boolean renameTo(File dest) {
1400ab3683bce6e370c946598bfad54387fa38ce69dfElliott Hughes        if (path.isEmpty() || dest.path.isEmpty()) {
1401c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes            return false;
1402c5c9c667028146ab5f5e446c44f911c2fdd7dd30Elliott Hughes        }
1403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SecurityManager security = System.getSecurityManager();
1404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (security != null) {
1405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkWrite(path);
1406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            security.checkWrite(dest.path);
1407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
140893a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        return renameToImpl(pathBytes, dest.pathBytes);
1409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private native boolean renameToImpl(byte[] pathExist, byte[] pathNew);
1412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a string containing a concise, human-readable description of this
1415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * file.
1416f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a printable representation of this file.
1418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
1420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
1421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return path;
1422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a Uniform Resource Identifier for this file. The URI is system
1426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * dependent and may not be transferable between different operating / file
1427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * systems.
1428f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an URI for this file.
1430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1431f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    @SuppressWarnings("nls")
1432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public URI toURI() {
1433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String name = getAbsoluteName();
1434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
1435f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            if (!name.startsWith("/")) {
1436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // start with sep.
1437f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                return new URI("file", null, new StringBuilder(
1438f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                        name.length() + 1).append('/').append(name).toString(),
1439f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                        null, null);
1440f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            } else if (name.startsWith("//")) {
1441f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson                return new URI("file", "", name, null); // UNC path
1442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1443f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            return new URI("file", null, name, null, null);
1444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (URISyntaxException e) {
1445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // this should never happen
1446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
1447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a Uniform Resource Locator for this file. The URL is system
1452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * dependent and may not be transferable between different operating / file
1453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * systems.
1454f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
1455f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     * @return a URL for this file.
1456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.MalformedURLException
1457f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *             if the path cannot be transformed into a URL.
145808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @deprecated use {@link #toURI} and {@link java.net.URI#toURL} to get
145908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * correct escaping of illegal characters.
1460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
146108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    @Deprecated
1462f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson    @SuppressWarnings("nls")
1463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public URL toURL() throws java.net.MalformedURLException {
1464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String name = getAbsoluteName();
1465f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        if (!name.startsWith("/")) {
1466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // start with sep.
1467c903e6720bbbf6540c29f141bd2fa559813ea20aElliott Hughes            return new URL("file", "", -1,
1468c903e6720bbbf6540c29f141bd2fa559813ea20aElliott Hughes                    new StringBuilder(name.length() + 1).append('/').append(name).toString(), null);
1469f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson        } else if (name.startsWith("//")) {
1470f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson            return new URL("file:" + name); // UNC path
1471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1472c903e6720bbbf6540c29f141bd2fa559813ea20aElliott Hughes        return new URL("file", "", -1, name, null);
1473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private String getAbsoluteName() {
1476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        File f = getAbsoluteFile();
1477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String name = f.getPath();
1478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (f.isDirectory() && name.charAt(name.length() - 1) != separatorChar) {
1480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Directories must end with a slash
1481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            name = new StringBuilder(name.length() + 1).append(name)
1482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    .append('/').toString();
1483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (separatorChar != '/') { // Must convert slashes.
1485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            name = name.replace(separatorChar, '/');
1486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return name;
1488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void writeObject(ObjectOutputStream stream) throws IOException {
1491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        stream.defaultWriteObject();
1492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        stream.writeChar(separatorChar);
1493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
149508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
1496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        stream.defaultReadObject();
1497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        char inSeparator = stream.readChar();
149893a4b2a6cc35a72aa5a58027025f3e18c0ec2e64Elliott Hughes        init(path.replace(inSeparator, separatorChar));
1499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
150008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
150108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    /**
150208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Returns the total size in bytes of the partition containing this path.
150308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Returns 0 if this path does not exist.
150408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *
150508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @since 1.6
150608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     */
150708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    public long getTotalSpace() {
150808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        SecurityManager security = System.getSecurityManager();
150908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        if (security != null) {
151008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes            security.checkPermission(new RuntimePermission("getFileSystemAttributes"));
151108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        }
151208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return getTotalSpaceImpl(pathBytes);
151308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    }
151408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    private native long getTotalSpaceImpl(byte[] filePath);
151508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
151608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    /**
151708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Returns the number of usable free bytes on the partition containing this path.
151808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Returns 0 if this path does not exist.
151908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *
152008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * <p>Note that this is likely to be an optimistic over-estimate and should not
152108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * be taken as a guarantee your application can actually write this many bytes.
152208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * On Android (and other Unix-based systems), this method returns the number of free bytes
152308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * available to non-root users, regardless of whether you're actually running as root,
152408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * and regardless of any quota or other restrictions that might apply to the user.
152508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * (The {@code getFreeSpace} method returns the number of bytes potentially available to root.)
152608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *
152708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @since 1.6
152808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     */
152908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    public long getUsableSpace() {
153008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        SecurityManager security = System.getSecurityManager();
153108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        if (security != null) {
153208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes            security.checkPermission(new RuntimePermission("getFileSystemAttributes"));
153308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        }
153408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return getUsableSpaceImpl(pathBytes);
153508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    }
153608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    private native long getUsableSpaceImpl(byte[] filePath);
153708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes
153808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    /**
153908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Returns the number of free bytes on the partition containing this path.
154008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * Returns 0 if this path does not exist.
154108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *
154208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * <p>Note that this is likely to be an optimistic over-estimate and should not
154308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * be taken as a guarantee your application can actually write this many bytes.
154408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     *
154508ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     * @since 1.6
154608ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes     */
154708ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    public long getFreeSpace() {
154808ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        SecurityManager security = System.getSecurityManager();
154908ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        if (security != null) {
155008ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes            security.checkPermission(new RuntimePermission("getFileSystemAttributes"));
155108ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        }
155208ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes        return getFreeSpaceImpl(pathBytes);
155308ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    }
155408ec8fd5c950cb94e12aefa08c89d78762acf18aElliott Hughes    private native long getFreeSpaceImpl(byte[] filePath);
1555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
1556