1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package ca.uhn.hl7v2.util.idgenerator;
27
28 import java.io.BufferedReader;
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.FileOutputStream;
32 import java.io.IOException;
33 import java.io.InputStreamReader;
34 import java.io.PrintWriter;
35 import java.util.concurrent.locks.ReentrantLock;
36
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import ca.uhn.hl7v2.util.Home;
41
42
43
44
45
46
47
48
49
50
51 public class FileBasedGenerator extends InMemoryIDGenerator {
52
53 private static final Logger LOG = LoggerFactory.getLogger(FileBasedGenerator.class.getName());
54
55 private String directory = Home.getHomeDirectory().getAbsolutePath();
56 private String fileName = "id_file";
57 private boolean neverFail = true;
58 private boolean used = false;
59 private boolean minimizeReads = false;
60 private final ReentrantLock lock = new ReentrantLock();
61
62 public FileBasedGenerator() {
63 this(1L);
64 }
65
66 public FileBasedGenerator(long increment) {
67 super(increment);
68 }
69
70 public String getID() throws IOException {
71 try {
72 lock.lock();
73
74
75 if (!minimizeReads || !used) {
76 long readInitialValue = readInitialValue(getFilePath());
77 if (readInitialValue >= 0) {
78 set(readInitialValue);
79 }
80 used = true;
81 }
82
83 String id = super.getID();
84
85
86 writeNextValue(Long.parseLong(id) + getIncrement());
87 return id;
88 } finally {
89 lock.unlock();
90 }
91 }
92
93
94 private void writeNextValue(long id) throws IOException {
95 try (PrintWriter pw = new PrintWriter(new FileOutputStream(getFilePath(), false))) {
96 pw.println(id);
97 } catch (IOException e) {
98 if (neverFail) {
99 LOG.warn("Could not write ID to file {}, going to use internal ID generator. {}",
100 getFilePath(), e.getMessage());
101 return;
102 }
103 throw e;
104 }
105 }
106
107 private long readInitialValue(String path) throws IOException {
108 BufferedReader br = null;
109 String id = null;
110 try {
111 br = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
112 id = br.readLine();
113 return Long.parseLong(id);
114 } catch (IOException e) {
115 LOG.info("Could not read ID file {} ", path);
116 if (!neverFail) {
117 throw e;
118 }
119 return -1;
120 } catch (NumberFormatException e) {
121 LOG.info("ID {} read from file is not a number", id);
122 return -1;
123 } finally {
124 if (br != null)
125 try {
126 br.close();
127 } catch (IOException ignored) {
128 }
129 }
130 }
131
132 private String getFilePath() {
133 return new File(directory, fileName).getAbsolutePath();
134 }
135
136 public void setDirectory(String directory) {
137 try {
138 lock.lock();
139 this.directory = directory;
140 } finally {
141 lock.unlock();
142 }
143 }
144
145 public void setFileName(String fileName) {
146 try {
147 lock.lock();
148 this.fileName = fileName;
149 } finally {
150 lock.unlock();
151 }
152 }
153
154
155
156
157
158
159
160 public void setMinimizeReads(boolean theMinimizeReads) {
161 minimizeReads = theMinimizeReads;
162 }
163
164
165
166
167
168
169
170
171 public void setNeverFail(boolean neverFail) {
172 this.neverFail = neverFail;
173 }
174
175 public void reset() {
176 try {
177 lock.lock();
178 super.reset();
179 writeNextValue(0L);
180 } catch (IOException e) {
181 throw new IllegalStateException("Cannot initialize persistent ID generator", e);
182 } finally {
183 lock.unlock();
184 }
185 }
186
187 }