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