Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
MessageIDGenerator |
|
| 4.5;4.5 |
1 | package ca.uhn.hl7v2.util; | |
2 | ||
3 | import java.io.File; | |
4 | import java.io.FileNotFoundException; | |
5 | import java.io.FileReader; | |
6 | import java.io.FileWriter; | |
7 | import java.io.IOException; | |
8 | ||
9 | import org.slf4j.Logger; | |
10 | import org.slf4j.LoggerFactory; | |
11 | ||
12 | import ca.uhn.hl7v2.util.idgenerator.FileBasedHiLoGenerator; | |
13 | ||
14 | /** | |
15 | * <p> | |
16 | * Creates unique message IDs. IDs are stored in a file called {@link Home#getHomeDirectory() hapi.home}/id_file for persistence | |
17 | * across JVM sessions. Note that if one day you run the JVM with a new working directory, | |
18 | * you must move or copy id_file into this directory so that new ID numbers will begin | |
19 | * with the last one used, rather than starting over again. | |
20 | * </p> | |
21 | * <p> | |
22 | * Note that as of HAPI 2.0, by default this class will not fail even if the id_file can | |
23 | * not be read/written. In this case, HAPI will try to fail gracefully by simply generating | |
24 | * a numeric sequence starting at zero. This behaviour can be overwritten using | |
25 | * {@link #NEVER_FAIL_PROPERTY} | |
26 | * </p> | |
27 | * Note: you should not use this class directory, but use the {@link IDGeneratorFactory} instead. | |
28 | * Also consider using {@link FileBasedHiLoGenerator} which provides better performance | |
29 | * | |
30 | * | |
31 | * @author Neal Acharya | |
32 | * @deprecated use one of the IDGenerator implementations | |
33 | */ | |
34 | public class MessageIDGenerator { | |
35 | ||
36 | 5 | private static final Logger ourLog = LoggerFactory.getLogger(MessageIDGenerator.class.getName()); |
37 | private static MessageIDGenerator messageIdGenerator; | |
38 | ||
39 | /** | |
40 | * Contains the complete path to the default ID file, which is a plain text file containing | |
41 | * the number corresponding to the last generated ID | |
42 | */ | |
43 | 5 | public final static String DEFAULT_ID_FILE = Home.getHomeDirectory().getAbsolutePath() + "/id_file"; |
44 | ||
45 | /** | |
46 | * System property key which indicates that this class should never fail. If this | |
47 | * system property is set to false (default is true), as in the following code:<br> | |
48 | * <code>System.setProperty(MessageIDGenerator.NEVER_FAIL_PROPERTY, Boolean.FALSE.toString());</code><br> | |
49 | * this class will fail if the underlying disk file can not be | |
50 | * read or written. This means you are roughly guaranteed a unique | |
51 | * ID number between JVM sessions (barring the file getting lost or corrupted). | |
52 | */ | |
53 | 5 | public static final String NEVER_FAIL_PROPERTY = MessageIDGenerator.class.getName() + "_NEVER_FAIL_PROPERTY"; |
54 | ||
55 | private long id; | |
56 | private FileWriter fileW; | |
57 | ||
58 | /** | |
59 | * Constructor | |
60 | * Creates an instance of the class | |
61 | * Its reads an id (longint#) from an external file, if one is not present then the external file | |
62 | * is created and initialized to zero. | |
63 | * This id is stored into the private field of id. | |
64 | */ | |
65 | 5 | private MessageIDGenerator() throws IOException { |
66 | 5 | initialize(); |
67 | 5 | }//end constructor code |
68 | ||
69 | ||
70 | /** | |
71 | * Force the generator to re-load the ID file and initialize itself. | |
72 | * | |
73 | * This method is mostly provided as a convenience to unit tests, and does | |
74 | * not normally need to be called. | |
75 | */ | |
76 | void initialize() throws IOException { | |
77 | 10 | id = 0; |
78 | ||
79 | /*check external file for the last value unique id value generated by | |
80 | this class*/ | |
81 | try{ | |
82 | // We should check to see if the external file for storing the unique ids exists | |
83 | 10 | File extFile = new File(DEFAULT_ID_FILE); |
84 | 10 | if (extFile.createNewFile()== true){ |
85 | /*there was no existing file so a new one has been created with createNewFile method. The | |
86 | file is stored at <hapi.home>/id_file.txt */ | |
87 | // We can simply initialize the private id field to zero | |
88 | 0 | id = 0; |
89 | ||
90 | }//end if | |
91 | else{ | |
92 | /*The file does exist which is why we received false from the | |
93 | createNewFile method. We should now try to read from this file*/ | |
94 | 10 | FileReader fileR = new FileReader(DEFAULT_ID_FILE); |
95 | 5 | char[] charArray = new char[100]; |
96 | 5 | int e = fileR.read(charArray); |
97 | 5 | if (e <= 0){ |
98 | /*We know the file exists but it has no value stored in it. So at this point we can simply initialize the | |
99 | private id field to zero*/ | |
100 | 0 | id = 0; |
101 | }//end if | |
102 | else{ | |
103 | /* Here we know that the file exists and has a stored value. we should read this value and set the | |
104 | private id field to it*/ | |
105 | 5 | String idStr = String.valueOf(charArray); |
106 | 5 | String idStrTrim = idStr.trim(); |
107 | ||
108 | try { | |
109 | 5 | id = Long.parseLong(idStrTrim); |
110 | 0 | } catch (NumberFormatException nfe) { |
111 | 0 | ourLog.warn("Failed to parse message ID file value \"" + idStrTrim + "\". Defaulting to 0."); |
112 | 5 | } |
113 | ||
114 | }//end else | |
115 | //Fix for bug 1100881: Close the file after writing. | |
116 | 5 | fileR.close(); |
117 | }//end else | |
118 | 5 | } catch (FileNotFoundException e) { |
119 | 5 | ourLog.error("Failed to locate message ID file. Message was: {}", e.getMessage()); |
120 | 0 | } catch (IOException e) { |
121 | 0 | if (Boolean.TRUE.equals(System.getProperty(NEVER_FAIL_PROPERTY, Boolean.TRUE.toString()))) { |
122 | 0 | ourLog.warn("Could not retrieve message ID file, going to default to ID of 0. Message was: {}", e.getMessage()); |
123 | 0 | id = 0; |
124 | 0 | return; |
125 | } else { | |
126 | 0 | throw e; |
127 | } | |
128 | 10 | } |
129 | 10 | } |
130 | ||
131 | /** | |
132 | * Synchronized method used to return the single (static) instance of the class | |
133 | */ | |
134 | public static synchronized MessageIDGenerator getInstance() throws IOException { | |
135 | 6015 | if (messageIdGenerator == null) |
136 | 5 | messageIdGenerator = new MessageIDGenerator(); |
137 | 6015 | return messageIdGenerator; |
138 | }//end method | |
139 | ||
140 | /** | |
141 | * Synchronized method used to return the incremented id value | |
142 | */ | |
143 | public synchronized String getNewID() throws IOException{ | |
144 | try { | |
145 | //increment the private field | |
146 | 6015 | id = id + 1; |
147 | //write the id value to the file | |
148 | 6015 | String idStr = String.valueOf(id); |
149 | ||
150 | //create an instance of the Filewriter Object pointing to "C:\\extfiles\\Idfile.txt" | |
151 | 6015 | fileW = new FileWriter(DEFAULT_ID_FILE, false); |
152 | 6010 | fileW.write(idStr); |
153 | 6010 | fileW.flush(); |
154 | 6010 | fileW.close(); |
155 | 5 | } catch (FileNotFoundException e) { |
156 | 5 | if (Boolean.TRUE.equals(System.getProperty(NEVER_FAIL_PROPERTY, Boolean.TRUE.toString()))) { |
157 | 0 | ourLog.info("Failed to create message ID file. Message was: {}", e.getMessage()); |
158 | 0 | fileW = null; |
159 | } | |
160 | 0 | } catch (IOException e) { |
161 | 0 | if (Boolean.TRUE.equals(System.getProperty(NEVER_FAIL_PROPERTY, Boolean.TRUE.toString()))) { |
162 | 0 | ourLog.debug("Failed to create message ID file. Message was: {}", e.getMessage()); |
163 | 0 | fileW = null; |
164 | } else { | |
165 | 0 | throw e; |
166 | } | |
167 | 6015 | } |
168 | 6015 | return String.valueOf(id); |
169 | }//end method | |
170 | ||
171 | } |