1/*
2 * Copyright (c) 2002-2012, the original author or authors.
3 *
4 * This software is distributable under the BSD license. See the terms of the
5 * BSD license in the documentation provided with this software.
6 *
7 * http://www.opensource.org/licenses/bsd-license.php
8 */
9package jdk.internal.jline.console.history;
10
11import java.io.BufferedOutputStream;
12import java.io.BufferedReader;
13import java.io.File;
14import java.io.FileOutputStream;
15import java.io.FileReader;
16import java.io.Flushable;
17import java.io.IOException;
18import java.io.InputStream;
19import java.io.InputStreamReader;
20import java.io.PrintStream;
21import java.io.Reader;
22
23import jdk.internal.jline.internal.Log;
24import static jdk.internal.jline.internal.Preconditions.checkNotNull;
25
26/**
27 * {@link History} using a file for persistent backing.
28 * <p/>
29 * Implementers should install shutdown hook to call {@link FileHistory#flush}
30 * to save history to disk.
31 *
32 * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
33 * @since 2.0
34 */
35public class FileHistory
36    extends MemoryHistory
37    implements PersistentHistory, Flushable
38{
39    private final File file;
40
41    public FileHistory(final File file) throws IOException {
42        this.file = checkNotNull(file);
43        load(file);
44    }
45
46    public File getFile() {
47        return file;
48    }
49
50    public void load(final File file) throws IOException {
51        checkNotNull(file);
52        if (file.exists()) {
53            Log.trace("Loading history from: ", file);
54            load(new FileReader(file));
55        }
56    }
57
58    public void load(final InputStream input) throws IOException {
59        checkNotNull(input);
60        load(new InputStreamReader(input));
61    }
62
63    public void load(final Reader reader) throws IOException {
64        checkNotNull(reader);
65        BufferedReader input = new BufferedReader(reader);
66
67        String item;
68        while ((item = input.readLine()) != null) {
69            internalAdd(item);
70        }
71    }
72
73    public void flush() throws IOException {
74        Log.trace("Flushing history");
75
76        if (!file.exists()) {
77            File dir = file.getParentFile();
78            if (!dir.exists() && !dir.mkdirs()) {
79                Log.warn("Failed to create directory: ", dir);
80            }
81            if (!file.createNewFile()) {
82                Log.warn("Failed to create file: ", file);
83            }
84        }
85
86        PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
87        try {
88            for (Entry entry : this) {
89                out.println(entry.value());
90            }
91        }
92        finally {
93            out.close();
94        }
95    }
96
97    public void purge() throws IOException {
98        Log.trace("Purging history");
99
100        clear();
101
102        if (!file.delete()) {
103            Log.warn("Failed to delete history file: ", file);
104        }
105    }
106}
107