1f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project *
3f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This program and the accompanying materials are made available under
4f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * the terms of the Common Public License v1.0 which accompanies this distribution,
5f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * and is available at http://www.eclipse.org/legal/cpl-v10.html
6f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project *
7f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * $Id: Files.java,v 1.1.1.1.2.1 2004/07/09 01:28:37 vlad_r Exp $
8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpackage com.vladium.util;
10f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
11f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.BufferedReader;
12f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.File;
13f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.FileReader;
14f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.IOException;
15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.ArrayList;
16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.HashSet;
17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.LinkedList;
18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.List;
19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Set;
20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.StringTokenizer;
21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------
23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/**
24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @author Vlad Roubtsov, (C) 2003
25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpublic
27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectabstract class Files
28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project{
29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // public: ................................................................
30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * No duplicate elimination.
33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param atfile
35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static String [] readFileList (final File atfile)
37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        throws IOException
38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (atfile == null) throw new IllegalArgumentException ("null input: atfile");
40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        List _result = null;
42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        BufferedReader in = null;
44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        try
45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            in = new BufferedReader (new FileReader (atfile), 8 * 1024); // uses default encoding
47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            _result = new LinkedList ();
48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (String line; (line = in.readLine ()) != null; )
50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                line = line.trim ();
52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if ((line.length () == 0) || (line.charAt (0) == '#')) continue;
53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                _result.add (line);
55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        finally
58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (in != null) try { in.close (); } catch (Exception ignore) {}
60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if ((_result == null) || _result.isEmpty ())
63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return IConstants.EMPTY_STRING_ARRAY;
64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        else
65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String [] result = new String [_result.size ()];
67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            _result.toArray (result);
68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return result;
70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * Converts an array of path segments to an array of Files. The order
75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * of files follows the original order of path segments, except "duplicate"
76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * entries are removed. The definition of duplicates depends on 'canonical':
77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * <ul>
78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *  <li> if 'canonical'=true, the pathnames are canonicalized via {@link #canonicalizePathname}
79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *  before they are compared for equality
80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *  <li> if 'canonical'=false, the pathnames are compared as case-sensitive strings
81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * </ul>
82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * Note that duplicate removal in classpaths affects ClassLoader.getResources().
84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * The first mode above makes the most sense, however the last one is what
85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * Sun's java.net.URLClassLoader appears to do. Hence the last mode might be
86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * necessary for reproducing its behavior in Sun-compatible JVMs.
87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static File [] pathToFiles (final String [] path, final boolean canonical)
89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (path == null) throw new IllegalArgumentException ("null input: path");
91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (path.length == 0) return IConstants.EMPTY_FILE_ARRAY;
92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final List /* Files */ _result = new ArrayList (path.length);
94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final Set /* String */ pathnames = new HashSet (path.length);
95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final String separators = ",".concat (File.pathSeparator);
97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        for (int i = 0; i < path.length; ++ i)
99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            String segment = path [i];
101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (segment == null) throw new IllegalArgumentException ("null input: path[" + i + "]");
102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final StringTokenizer tokenizer = new StringTokenizer (segment, separators);
104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            while (tokenizer.hasMoreTokens ())
105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                String pathname = tokenizer.nextToken ();
107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (canonical) pathname = canonicalizePathname (pathname);
109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if (pathnames.add (pathname))
111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    _result.add (new File (pathname));
113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final File [] result = new File [_result.size ()];
118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        _result.toArray (result);
119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return result;
121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * Converts 'pathname' into the canonical OS form. This wrapper function
125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * will return the absolute form of 'pathname' if File.getCanonicalPath() fails.
126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static String canonicalizePathname (final String pathname)
128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (pathname == null) throw new IllegalArgumentException ("null input: pathname");
130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        try
132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return new File (pathname).getCanonicalPath ();
134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        catch (Exception e)
136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return new File (pathname).getAbsolutePath ();
138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static File canonicalizeFile (final File file)
142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (file == null) throw new IllegalArgumentException ("null input: file");
144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        try
146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return file.getCanonicalFile ();
148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        catch (Exception e)
150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return file.getAbsoluteFile ();
152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * Invariant: (getFileName (file) + getFileExtension (file)).equals (file.getName ()).
157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param file File input file descriptor [must be non-null]
159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @return String file name without the extension [excluding '.' separator]
161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * [if 'file' does not appear to have an extension, the full name is returned].
162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @throws IllegalArgumentException if 'file' is null
164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static String getFileName (final File file)
166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (file == null) throw new IllegalArgumentException ("null input: file");
168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final String name = file.getName ();
170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        int lastDot = name.lastIndexOf ('.');
171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (lastDot < 0) return name;
172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return name.substring (0, lastDot);
174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * Invariant: (getFileName (file) + getFileExtension (file)).equals (file.getName ()).
178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param file File input file descriptor [must be non-null]
180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @return String extension [including '.' separator] or "" if 'file' does not
182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * appear to have an extension.
183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @throws IllegalArgumentException if 'file' is null
185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static String getFileExtension (final File file)
187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (file == null) throw new IllegalArgumentException ("null input: file");
189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final String name = file.getName ();
191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        int lastDot = name.lastIndexOf ('.');
192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (lastDot < 0) return "";
193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return name.substring (lastDot);
195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param dir [null is ignored]
200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param file [absolute overrides 'dir']
201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @return
202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static File newFile (final File dir, final File file)
204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (file == null) throw new IllegalArgumentException ("null input: file");
206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if ((dir == null) || file.isAbsolute ()) return file;
208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return new File (dir, file.getPath ());
210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param dir [null is ignored]
215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param file [absolute overrides 'dir']
216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @return
217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static File newFile (final File dir, final String file)
219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (file == null) throw new IllegalArgumentException ("null input: file");
221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final File fileFile  = new File (file);
223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if ((dir == null) || fileFile.isAbsolute ()) return fileFile;
224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return new File (dir, file);
226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param dir [null is ignored]
231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param file [absolute overrides 'dir']
232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @return
233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static File newFile (final String dir, final String file)
235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (file == null) throw new IllegalArgumentException ("null input: file");
237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final File fileFile  = new File (file);
239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if ((dir == null) || fileFile.isAbsolute ()) return fileFile;
240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return new File (dir, file);
242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * Renames 'source' to 'target' [intermediate directories are created if necessary]. If
246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * 'target' exists and 'overwrite' is false, the method is a no-op. No exceptions are
247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * thrown except for when input is invalid. If the operation fails half-way it can leave
248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * some file system artifacts behind.
249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @return true iff the renaming was actually performed.
251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param source file descriptor [file must exist]
253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param target target file descriptor [an existing target may get deleted
254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * if 'overwrite' is true]
255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param overwrite if 'true', forces an existing target to be deleted
256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @throws IllegalArgumentException if 'source' is null or file does not exist
258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @throws IllegalArgumentException if 'target' is null
259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static boolean renameFile (final File source, final File target, final boolean overwrite)
261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if ((source == null) || ! source.exists ())
263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            throw new IllegalArgumentException ("invalid input source: [" + source + "]");
264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (target == null)
265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            throw new IllegalArgumentException ("null input: target");
266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final boolean targetExists;
268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (! (targetExists = target.exists ()) || overwrite)
269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (targetExists)
271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // need to delete the target first or the rename will fail:
273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                target.delete (); // not checking the result here: let the rename fail later
274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            else
276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // note that File.renameTo() does not create intermediate directories on demand:
278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                final File targetDir = target.getParentFile ();
279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                if ((targetDir != null) && ! targetDir.equals (source.getParentFile ()))
280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    targetDir.mkdirs (); // TODO: clean this up on failure?
281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // note: this can fail for a number of reasons, including the target
284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            // being on a different drive/file system:
285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            return source.renameTo (target);
286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return false;
289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /**
292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * A slightly stricter version of File.createTempFile() in J2SDK 1.3: it requires
293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * that the caller provide an existing parent directory for the temp file.
294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * This defers to File.createTempFile (prefix, extension, parentDir) after
295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * normalizing 'extension'.<P>
296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * MT-safety: if several threads use this API concurrently, the temp files
298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * created are guaranteed to get created without any collisions and correspond
299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * to files that did not exist before. However, if such a temp file is deleted
300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * at a later point, this method may reuse its file name. These MT-safety
301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * guarantees do not hold if files are created in the same directory outside
302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * of this method.
303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param parentDir parent dir for the temp file [may not be null and must exist]
305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param prefix prefix pattern for the temp file name [only the first 3
306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * chars are guaranteed to be used]
307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @param extension pattern for the temp file name [null is equivalient to
308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * ".tmp"; this is always normalized to start with "."; only the first 3
309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * non-"." chars are guaranteed to be used]
310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     *
311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @return writeable temp file descriptor [incorporates 'parentDir' in its pathname]
312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * @throws IOException if a temp file could not be created
313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public static File createTempFile (final File parentDir, final String prefix, String extension)
315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        throws IOException
316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if ((parentDir == null) || ! parentDir.exists ())
318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            throw new IllegalArgumentException ("invalid parent directory: [" + parentDir + "]");
319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if ((prefix == null) || (prefix.length () < 3))
320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            throw new IllegalArgumentException ("null or less than 3 chars long: " + prefix);
321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (extension == null) extension = ".tmp";
323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        else if (extension.charAt (0) != '.') extension = ".".concat (extension);
324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        return File.createTempFile (prefix, extension, parentDir);
326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // protected: .............................................................
329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // package: ...............................................................
331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // private: ...............................................................
333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private Files () {} // prevent subclassing
336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project} // end of class
338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------