source: josm/trunk/src/org/openstreetmap/josm/io/CacheCustomContent.java@ 5874

Last change on this file since 5874 was 5874, checked in by Don-vip, 11 years ago

see #8570, #7406 - I/O refactorization:

  • Move different file copy functions to Utils.copyFile (to be replaced later by Files.copy when switching to Java 7)
  • Replace all Utils.close(XXX) by Utils.close(Closeable) -> impacted plugins: commandline, mirrored_download, opendata, piclayer
  • Add new Utils.close(ZipFile)
  • Use of Utils.close almost everywhere
  • Javadoc fixes
  • Property svn:eol-style set to native
File size: 5.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io;
3
4import java.io.BufferedInputStream;
5import java.io.BufferedOutputStream;
6import java.io.File;
7import java.io.FileInputStream;
8import java.io.FileOutputStream;
9import java.io.IOException;
10import java.io.UnsupportedEncodingException;
11import java.util.Date;
12
13import org.openstreetmap.josm.Main;
14import org.openstreetmap.josm.tools.Utils;
15
16/**
17 * Use this class if you want to cache and store a single file that gets updated regularly.
18 * Unless you flush() it will be kept in memory. If you want to cache a lot of data and/or files,
19 * use CacheFiles
20 * @param <T> a {@link Throwable} that may be thrown during {@link #updateData()},
21 * use {@link RuntimeException} if no exception must be handled.
22 * @author xeen
23 *
24 */
25public abstract class CacheCustomContent<T extends Throwable> {
26 /**
27 * Common intervals
28 */
29 final static public int INTERVAL_ALWAYS = -1;
30 final static public int INTERVAL_HOURLY = 60*60;
31 final static public int INTERVAL_DAILY = INTERVAL_HOURLY * 24;
32 final static public int INTERVAL_WEEKLY = INTERVAL_DAILY * 7;
33 final static public int INTERVAL_MONTHLY = INTERVAL_WEEKLY * 4;
34 final static public int INTERVAL_NEVER = Integer.MAX_VALUE;
35
36 /**
37 * Where the data will be stored
38 */
39 private byte[] data = null;
40
41 /**
42 * The ident that identifies the stored file. Includes file-ending.
43 */
44 final private String ident;
45
46 /**
47 * The (file-)path where the data will be stored
48 */
49 final private File path;
50
51 /**
52 * How often to update the cached version
53 */
54 final private int updateInterval;
55
56 /**
57 * This function will be executed when an update is required. It has to be implemented by the
58 * inheriting class and should use a worker if it has a long wall time as the function is
59 * executed in the current thread.
60 * @return the data to cache
61 */
62 protected abstract byte[] updateData() throws T;
63
64 /**
65 * This function serves as a comfort hook to perform additional checks if the cache is valid
66 * @return True if the cached copy is still valid
67 */
68 protected boolean isCacheValid() {
69 return true;
70 }
71
72 /**
73 * Initializes the class. Note that all read data will be stored in memory until it is flushed
74 * by flushData().
75 * @param ident
76 * @param updateInterval
77 */
78 public CacheCustomContent(String ident, int updateInterval) {
79 this.ident = ident;
80 this.updateInterval = updateInterval;
81 this.path = new File(Main.pref.getCacheDirectory(), ident);
82 }
83
84 /**
85 * Updates data if required
86 * @return Returns the data
87 */
88 public byte[] updateIfRequired() throws T {
89 if (Main.pref.getInteger("cache." + ident, 0) + updateInterval < new Date().getTime()/1000
90 || !isCacheValid())
91 return updateForce();
92 return getData();
93 }
94
95 /**
96 * Updates data if required
97 * @return Returns the data as string
98 */
99 public String updateIfRequiredString() throws T {
100 if (Main.pref.getInteger("cache." + ident, 0) + updateInterval < new Date().getTime()/1000
101 || !isCacheValid())
102 return updateForceString();
103 return getDataString();
104 }
105
106 /**
107 * Executes an update regardless of updateInterval
108 * @return Returns the data
109 */
110 public byte[] updateForce() throws T {
111 this.data = updateData();
112 saveToDisk();
113 Main.pref.putInteger("cache." + ident, (int)(new Date().getTime()/1000));
114 return data;
115 }
116
117 /**
118 * Executes an update regardless of updateInterval
119 * @return Returns the data as String
120 */
121 public String updateForceString() throws T {
122 updateForce();
123 try {
124 return new String(data, "utf-8");
125 } catch (UnsupportedEncodingException e){
126 e.printStackTrace();
127 return "";
128 }
129 }
130
131 /**
132 * Returns the data without performing any updates
133 * @return the data
134 */
135 public byte[] getData() throws T {
136 if (data == null) {
137 loadFromDisk();
138 }
139 return data;
140 }
141
142 /**
143 * Returns the data without performing any updates
144 * @return the data as String
145 */
146 public String getDataString() throws T {
147 try {
148 return new String(getData(), "utf-8");
149 } catch(UnsupportedEncodingException e){
150 e.printStackTrace();
151 return "";
152 }
153 }
154
155 /**
156 * Tries to load the data using the given ident from disk. If this fails, data will be updated
157 */
158 private void loadFromDisk() throws T {
159 if (Main.applet)
160 this.data = updateForce();
161 else {
162 BufferedInputStream input = null;
163 try {
164 input = new BufferedInputStream(new FileInputStream(path));
165 this.data = new byte[input.available()];
166 input.read(this.data);
167 } catch (IOException e) {
168 this.data = updateForce();
169 } finally {
170 Utils.close(input);
171 }
172 }
173 }
174
175 /**
176 * Stores the data to disk
177 */
178 private void saveToDisk() {
179 if (Main.applet)
180 return;
181 BufferedOutputStream output = null;
182 try {
183 output = new BufferedOutputStream(new FileOutputStream(path));
184 output.write(this.data);
185 output.flush();
186 } catch(Exception e) {
187 e.printStackTrace();
188 } finally {
189 Utils.close(output);
190 }
191 }
192
193 /**
194 * Flushes the data from memory. Class automatically reloads it from disk or updateData() if
195 * required
196 */
197 public void flushData() {
198 data = null;
199 }
200}
Note: See TracBrowser for help on using the repository browser.