View Javadoc

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  	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      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      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      private  MessageIDGenerator() throws IOException {
66          initialize();
67      }//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      	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              File extFile = new File(DEFAULT_ID_FILE);
84              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                  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                  FileReader fileR = new FileReader(DEFAULT_ID_FILE);
95                  char[] charArray = new char[100];
96                  int e = fileR.read(charArray);
97                  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                     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 }