1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package libcore.io;
19
20
21import java.io.File;
22import java.util.ArrayList;
23import java.util.Collections;
24
25/**
26 * Implements the actual DeleteOnExit mechanism. Is registered as a shutdown
27 * hook in the Runtime, once it is actually being used.
28 */
29public class DeleteOnExit extends Thread {
30
31    /**
32     * Our singleton instance.
33     */
34    private static DeleteOnExit instance;
35
36    /**
37     * Returns our singleton instance, creating it if necessary.
38     */
39    public static synchronized DeleteOnExit getInstance() {
40        if (instance == null) {
41            instance = new DeleteOnExit();
42            Runtime.getRuntime().addShutdownHook(instance);
43        }
44
45        return instance;
46    }
47
48    /**
49     * Our list of files scheduled for deletion.
50     */
51    private final ArrayList<String> files = new ArrayList<String>();
52
53
54    private DeleteOnExit() {
55    }
56
57    /**
58     * Schedules a file for deletion.
59     *
60     * @param filename The file to delete.
61     */
62    public void addFile(String filename) {
63        synchronized (files) {
64            if (!files.contains(filename)) {
65                files.add(filename);
66            }
67        }
68    }
69
70    /**
71     * Does the actual work. Note we (a) first sort the files lexicographically
72     * and then (b) delete them in reverse order. This is to make sure files
73     * get deleted before their parent directories.
74     */
75    @Override
76    public void run() {
77        Collections.sort(files);
78        for (int i = files.size() - 1; i >= 0; i--) {
79            new File(files.get(i)).delete();
80        }
81    }
82}
83