001package ca.uhn.hl7v2.util; 002 003import java.io.File; 004import java.io.FileNotFoundException; 005import java.io.FileReader; 006import java.io.FileWriter; 007import java.io.IOException; 008 009import org.slf4j.Logger; 010import org.slf4j.LoggerFactory; 011 012import ca.uhn.hl7v2.util.idgenerator.FileBasedHiLoGenerator; 013 014/** 015 * <p> 016 * Creates unique message IDs. IDs are stored in a file called {@link Home#getHomeDirectory() hapi.home}/id_file for persistence 017 * across JVM sessions. Note that if one day you run the JVM with a new working directory, 018 * you must move or copy id_file into this directory so that new ID numbers will begin 019 * with the last one used, rather than starting over again. 020 * </p> 021 * <p> 022 * Note that as of HAPI 2.0, by default this class will not fail even if the id_file can 023 * not be read/written. In this case, HAPI will try to fail gracefully by simply generating 024 * a numeric sequence starting at zero. This behaviour can be overwritten using 025 * {@link #NEVER_FAIL_PROPERTY} 026 * </p> 027 * Note: you should not use this class directory, but use the {@link IDGeneratorFactory} instead. 028 * Also consider using {@link FileBasedHiLoGenerator} which provides better performance 029 * 030 * 031 * @author Neal Acharya 032 * @deprecated use one of the IDGenerator implementations 033 */ 034public class MessageIDGenerator { 035 036 private static final Logger ourLog = LoggerFactory.getLogger(MessageIDGenerator.class.getName()); 037 private static MessageIDGenerator messageIdGenerator; 038 039 /** 040 * Contains the complete path to the default ID file, which is a plain text file containing 041 * the number corresponding to the last generated ID 042 */ 043 public final static String DEFAULT_ID_FILE = Home.getHomeDirectory().getAbsolutePath() + "/id_file"; 044 045 /** 046 * System property key which indicates that this class should never fail. If this 047 * system property is set to false (default is true), as in the following code:<br> 048 * <code>System.setProperty(MessageIDGenerator.NEVER_FAIL_PROPERTY, Boolean.FALSE.toString());</code><br> 049 * this class will fail if the underlying disk file can not be 050 * read or written. This means you are roughly guaranteed a unique 051 * ID number between JVM sessions (barring the file getting lost or corrupted). 052 */ 053 public static final String NEVER_FAIL_PROPERTY = MessageIDGenerator.class.getName() + "_NEVER_FAIL_PROPERTY"; 054 055 private long id; 056 private FileWriter fileW; 057 058 /** 059 * Constructor 060 * Creates an instance of the class 061 * Its reads an id (longint#) from an external file, if one is not present then the external file 062 * is created and initialized to zero. 063 * This id is stored into the private field of id. 064 */ 065 private MessageIDGenerator() throws IOException { 066 initialize(); 067 }//end constructor code 068 069 070 /** 071 * Force the generator to re-load the ID file and initialize itself. 072 * 073 * This method is mostly provided as a convenience to unit tests, and does 074 * not normally need to be called. 075 */ 076 void initialize() throws IOException { 077 id = 0; 078 079 /*check external file for the last value unique id value generated by 080 this class*/ 081 try{ 082 // We should check to see if the external file for storing the unique ids exists 083 File extFile = new File(DEFAULT_ID_FILE); 084 if (extFile.createNewFile()== true){ 085 /*there was no existing file so a new one has been created with createNewFile method. The 086 file is stored at <hapi.home>/id_file.txt */ 087 // We can simply initialize the private id field to zero 088 id = 0; 089 090 }//end if 091 else{ 092 /*The file does exist which is why we received false from the 093 createNewFile method. We should now try to read from this file*/ 094 FileReader fileR = new FileReader(DEFAULT_ID_FILE); 095 char[] charArray = new char[100]; 096 int e = fileR.read(charArray); 097 if (e <= 0){ 098 /*We know the file exists but it has no value stored in it. So at this point we can simply initialize the 099 private id field to zero*/ 100 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 String idStr = String.valueOf(charArray); 106 String idStrTrim = idStr.trim(); 107 108 try { 109 id = Long.parseLong(idStrTrim); 110 } catch (NumberFormatException nfe) { 111 ourLog.warn("Failed to parse message ID file value \"" + idStrTrim + "\". Defaulting to 0."); 112 } 113 114 }//end else 115 //Fix for bug 1100881: Close the file after writing. 116 fileR.close(); 117 }//end else 118 } catch (FileNotFoundException e) { 119 ourLog.error("Failed to locate message ID file. Message was: {}", e.getMessage()); 120 } catch (IOException e) { 121 if (Boolean.TRUE.equals(System.getProperty(NEVER_FAIL_PROPERTY, Boolean.TRUE.toString()))) { 122 ourLog.warn("Could not retrieve message ID file, going to default to ID of 0. Message was: {}", e.getMessage()); 123 id = 0; 124 return; 125 } else { 126 throw e; 127 } 128 } 129 } 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 if (messageIdGenerator == null) 136 messageIdGenerator = new MessageIDGenerator(); 137 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 id = id + 1; 147 //write the id value to the file 148 String idStr = String.valueOf(id); 149 150 //create an instance of the Filewriter Object pointing to "C:\\extfiles\\Idfile.txt" 151 fileW = new FileWriter(DEFAULT_ID_FILE, false); 152 fileW.write(idStr); 153 fileW.flush(); 154 fileW.close(); 155 } catch (FileNotFoundException e) { 156 if (Boolean.TRUE.equals(System.getProperty(NEVER_FAIL_PROPERTY, Boolean.TRUE.toString()))) { 157 ourLog.info("Failed to create message ID file. Message was: {}", e.getMessage()); 158 fileW = null; 159 } 160 } catch (IOException e) { 161 if (Boolean.TRUE.equals(System.getProperty(NEVER_FAIL_PROPERTY, Boolean.TRUE.toString()))) { 162 ourLog.debug("Failed to create message ID file. Message was: {}", e.getMessage()); 163 fileW = null; 164 } else { 165 throw e; 166 } 167 } 168 return String.valueOf(id); 169 }//end method 170 171}