001 package org.LiveGraph.dataFile.write; 002 003 import java.io.File; 004 import java.io.FileNotFoundException; 005 import java.io.FileOutputStream; 006 import java.util.Calendar; 007 import java.util.GregorianCalendar; 008 009 010 011 /** 012 * This class provides static convenience methods for creating dedicated data stream writers. 013 * Given just a directory on the local hard drive, this class can automatically 014 * choose a descriptive and unique name for a data file and return an appropriate 015 * {@link DataStreamWriter} object.<br /> 016 * <br /> 017 * An example of how to use this class can be found in 018 * {@link org.LiveGraph.demoDataSource.LiveGraphDemo}.<br /> 019 * 020 * <p style="font-size:smaller;">This product includes software developed by the 021 * <strong>LiveGraph</strong> project and its contributors.<br /> 022 * (<a href="http://www.live-graph.org" target="_blank">http://www.live-graph.org</a>)<br /> 023 * Copyright (c) 2007 G. Paperin.<br /> 024 * All rights reserved. 025 * </p> 026 * <p style="font-size:smaller;">File: DataStreamWriterFactory.java</p> 027 * <p style="font-size:smaller;">Redistribution and use in source and binary forms, with or 028 * without modification, are permitted provided that the following terms and conditions are met: 029 * </p> 030 * <p style="font-size:smaller;">1. Redistributions of source code must retain the above 031 * acknowledgement of the LiveGraph project and its web-site, the above copyright notice, 032 * this list of conditions and the following disclaimer.<br /> 033 * 2. Redistributions in binary form must reproduce the above acknowledgement of the 034 * LiveGraph project and its web-site, the above copyright notice, this list of conditions 035 * and the following disclaimer in the documentation and/or other materials provided with 036 * the distribution.<br /> 037 * 3. All advertising materials mentioning features or use of this software or any derived 038 * software must display the following acknowledgement:<br /> 039 * <em>This product includes software developed by the LiveGraph project and its 040 * contributors.<br />(http://www.live-graph.org)</em><br /> 041 * 4. All advertising materials distributed in form of HTML pages or any other technology 042 * permitting active hyper-links that mention features or use of this software or any 043 * derived software must display the acknowledgment specified in condition 3 of this 044 * agreement, and in addition, include a visible and working hyper-link to the LiveGraph 045 * homepage (http://www.live-graph.org). 046 * </p> 047 * <p style="font-size:smaller;">THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY 048 * OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 049 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 050 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 051 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 052 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 053 * </p> 054 * 055 * @author Greg Paperin (<a href="http://www.paperin.org" target="_blank">http://www.paperin.org</a>) 056 * @version {@value org.LiveGraph.LiveGraph#version} 057 */ 058 public class DataStreamWriterFactory { 059 060 /** 061 * Data file extension used if no other specified. 062 */ 063 public static final String defaultFileExtension = "dat"; 064 065 066 /** 067 * Creates a new {@link DataStreamWriter} object for a unique file located in the 068 * specified directory. The file will be named on the basis of the specified name and the 069 * current date and time.<br /> 070 * The file name will be constructed according to the following pattern:<br /> 071 * {@code dataFileName.YY.MM.DD-HH.MM.SS.}{@value #defaultFileExtension} 072 * 073 * @param dataFileDir The local folder in thich the file will be located. 074 * @param dataFileName The basis for the file name. 075 * @return A {@code DataStreamWriter} for the file with the name described above. 076 */ 077 public static DataStreamWriter createDataWriter(String dataFileDir, String dataFileName) { 078 return createDataWriter(dataFileDir, dataFileName, defaultFileExtension); 079 } 080 081 /** 082 * Creates a new {@link DataStreamWriter} object for a unique file located in the 083 * specified directory. The file will be named on the basis of the specified name, the 084 * specified extension and the current date and time.<br /> 085 * The file name will be constructed according to the following pattern:<br /> 086 * {@code dataFileName.YY.MM.DD-HH.MM.SS.dataFileExt} 087 * 088 * @param dataFileDir The local folder in thich the file will be located. 089 * @param dataFileName The basis for the file name. 090 * @param dataFileExt The extension for the file name. 091 * @return A {@code DataStreamWriter} for the file with the name described above. 092 */ 093 public static DataStreamWriter createDataWriter(String dataFileDir, String dataFileName, String dataFileExt) { 094 File file = getUniqueDataFile(dataFileDir, dataFileName, dataFileExt); 095 final int MAX_RETRY = 5; 096 for (int retry = 0; retry < MAX_RETRY; retry++) { 097 098 try { 099 FileOutputStream outs = new FileOutputStream(file); 100 DataStreamWriter writer = new DataStreamWriter(outs); 101 return writer; 102 } catch (FileNotFoundException e) { 103 Thread.yield(); 104 try {Thread.sleep((int) (Math.random() * 1000)); } 105 catch (InterruptedException e2) {} 106 Thread.yield(); 107 } 108 } 109 throw new Error("Cannot create data writer. Something weird is happening concurrently."); 110 } 111 112 113 /** 114 * Constructs a unique file name for a file located in the specified directory. The file will 115 * be named on the basis of the specified name, the specified extension and the current date 116 * and time.<br /> 117 * The file name will be constructed according to the following pattern:<br /> 118 * {@code dataFileName.YY.MM.DD-HH.MM.SS.dataFileExt} <br /> 119 * If that file already exists, the file name will be adjusted to <br /> 120 * {@code dataFileName.YY.MM.DD-HH.MM.SS(1).dataFileExt}, <br /> 121 * {@code dataFileName.YY.MM.DD-HH.MM.SS(2).dataFileExt}, <br /> 122 * and so on until the file does not already exist. 123 * 124 * @param dataFileDir The local folder in thich the file will be located. 125 * @param dataFileName The basis for the file name. 126 * @param dataFileExt The extension for the file name. 127 * @return A file object describing a file with the name as specified above. 128 */ 129 public static File getUniqueDataFile(String dataFileDir, String dataFileName, String dataFileExt) { 130 131 if (null == dataFileDir) 132 throw new NullPointerException("Data file directory cannot be null"); 133 134 if (null == dataFileName) 135 throw new NullPointerException("Data file name basis cannot be null"); 136 137 if (null == dataFileExt) 138 throw new NullPointerException("Data file extension cannot be null"); 139 140 if (dataFileDir.trim().length() > 0 && !dataFileDir.endsWith("/") && !dataFileDir.endsWith("\\")) 141 dataFileDir = dataFileDir + "/"; 142 143 while (dataFileDir.length() > 1 && dataFileDir.startsWith(".")) 144 dataFileDir = dataFileDir.substring(1); 145 146 Calendar date = new GregorianCalendar(); 147 String fName = String.format("%s.%2$ty.%2$tm.%2$td-%2$tH.%2$tM.%2$tS.%3$s", dataFileName, date, dataFileExt); 148 File dataFile = new File(dataFileDir + fName); 149 if (dataFile.exists()) { 150 int k = 1; 151 while(dataFile.exists()) { 152 fName = String.format("%1$s.%2$ty.%2$tm.%2$td-%2$tH.%2$tM.%2$tS(%4$d).%3$s", 153 dataFileName, date, dataFileExt, k); 154 dataFile = new File(dataFileDir + fName); 155 k++; 156 } 157 } 158 159 return dataFile; 160 } 161 162 } // public class DataStreamWriterFactory