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

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

see #8902 - Small performance enhancements / coding style (patch by shinigami):

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