1 /*
  2  * Copyright © [2008-2009] Novell, Inc.	All Rights Reserved.
  3  *
  4  * USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE DEVELOPER LICENSE AGREEMENT
  5  * OR OTHER AGREEMENT THROUGH WHICH NOVELL, INC. MAKES THE WORK AVAILABLE.	THIS WORK
  6  * MAY NOT BE ADAPTED WITHOUT NOVELL'S PRIOR WRITTEN CONSENT.
  7  *
  8  * NOVELL PROVIDES THE WORK "AS IS," WITHOUT ANY EXPRESS OR IMPLIED WARRANTY,
  9  * INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
 10  * A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.	NOVELL, THE AUTHORS OF THE WORK, AND THE
 11  * OWNERS OF COPYRIGHT IN THE WORK ARE NOT LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER
 12  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF,
 13  * OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS IN THE WORK.
 14  */
 15 /**
 16  * @fileoverview
 17  * This file contains a variety of file utility functions used by Collectors.
 18  */
 19 /**
 20  * Creates a File object which references an open file on the local system.
 21  * The path to the file must be absolute, and the file must be located within
 22  * the ESEC_HOME/data or ESEC_HOME/log directories (use the File Connector
 23  * or File Integrator to read/write files outside ESEC_HOME).
 24  * <p>Example:
 25  * <pre>
 26  * var myFile=new File(instance.CONFIG.collDir + "/myfile.mine");
 27  * </pre>
 28  * Several pre-defined variables are provided to assist in locating files:
 29  * <ul>
 30  * <li>instance.CONFIG.esecDir - ESEC_HOME directory (with slash)</li>
 31  * <li>instance.CONFIG.logDir - the Sentinel log directory (ESEC_HOME/log)</li>
 32  * <li>instance.CONFIG.commonDir - Storage area for Collector common resource files</li>
 33  * <li>instance.CONFIG.collDir - the directory in which the Collector plug-in is unpacked, along with any auxiliary files</li>
 34  * </ul>
 35  * @class
 36  * This class is used to manipulate files in the Collector.
 37  * @param {String} fileName	The absolute path and file name to open
 38  * @param {String} mode	The mode to open the file in, use "w" or "W" for write mode
 39  * @constructor
 40  */
 41 function File(fileName, mode){
 42 
 43 	this.name = fileName; // name property contains the name of the file.
 44 	this.eol = java.lang.System.getProperty("line.separator");
 45 	this.readLimit = 1048576;
 46 	
 47 	if (typeof fileName != "undefined") {
 48 		try {
 49 			if ((mode == "w" || mode == "W") && 
 50 			// Restrict file writes to Sentinel dir
 51 			(fileName.substr(0, instance.CONFIG.esecDir.length + 4) == instance.CONFIG.esecDir + "data" ||
 52 			fileName.substr(0, instance.CONFIG.esecDir.length + 3) == instance.CONFIG.esecDir + "log")) {
 53 				this.output = new java.io.BufferedWriter(new java.io.FileWriter(fileName, true));
 54 			}	else {
 55 				this.input = new java.io.BufferedReader(new java.io.FileReader(fileName));
 56 			}
 57 			this.offset = 0; //offset property holds file pointer's current position
 58 		} 
 59 		catch (err) {
 60 			log("Unable to open file " + fileName + ". Error:" + err, 5, instance.LOG);
 61 		}
 62 	}
 63 	// Some constants
 64 		
 65 	/**
 66 	 * Checks if the file is currently opened in read or write mode.
 67 	 * @return {boolean}	true if file was opened ; false if file closed .
 68 	 */
 69 	this.isOpen = function(){
 70 		if (typeof this.input != "undefined" || typeof this.output != "undefined") {
 71 			return true;
 72 		}
 73 		return false;
 74 	};
 75 
 76 	/**
 77 	 * Reads a line from the file.
 78 	 * @return	{String}
 79 	 */
 80 	this.readLine = function(){
 81 		var outString = "";
 82 		if (typeof this.input != 'undefined' && this.input.ready()) {
 83 			outString = String(this.input.readLine());
 84 			//updating the current offset of the file 
 85 			this.offset += ((outString + this.eol).length * 2);
 86 			return outString;
 87 		}
 88 		else {
 89 			return undefined;
 90 		}
 91 	};
 92 
 93 	/**
 94 	 * Writes a line to the file and optionally appends a line separator
 95 	 * @param {String} line to be written
 96 	 * @param {Boolean} addLnSep	boolean flag that tells to append line seperator or not
 97 	 * @return {Boolean} Status of the write attempt
 98 	 */
 99 	this.writeLine = function(line, addLnSep){
100 		if (typeof this.output != 'undefined' && typeof line != 'undefined') {
101 			if (addLnSep === false) {
102 				this.output.write(line);
103 			} else {
104 				this.output.write(line + this.eol);
105 			}
106 			this.output.flush();
107 			return true;
108 		} else {
109 			return false;
110 		}
111 	};
112 
113 	/**
114 	 * Reads an entire file into memory from the current position.
115 	 * This method is limited to read a maximum of 512k characters (i.e 524288 characters).
116 	 * @return {String} The file contents as single string. else 'undefined' if it fails due to any reason.
117 	 */
118 	this.readFile = function(){
119 		if (typeof this.input == 'undefined' || !this.input.ready()) {
120 			return undefined;
121 		}
122 		
123 		var fileString = "";
124 		var file = java.io.File(this.name);
125 		if ((file.length() - this.offset) < this.readLimit) {
126 			for (var inString = this.readLine(); typeof inString != 'undefined'; inString = this.readLine()) {
127 					fileString += inString + this.eol;
128 			}
129 			return fileString;
130 		} else {
131 			log("The contents read from the file " + this.name + " exceeds 1MB size limit. Workaround : use readLine() function n times to read n lines.", 5, instance.LOG);
132 			return undefined;
133 		}
134 	};
135 
136 	/**
137 	 * Closes the file.
138 	 */
139 	this.close = function(){
140 		if (typeof this.input != 'undefined') {
141 			this.input.close();
142 			this.input = undefined;
143 		}
144 		if (typeof this.output != 'undefined') {
145 			this.output.close();
146 			this.output = undefined;
147 		}
148 		this.offset = 0; //Resetting the offset of file to zero
149 	};	
150 }
151 
152 
153 
154 /**
155  * Fetches a list of files that matches a standard file glob pattern.
156  * @param {String}	dir
157  * @param {Regular Expression literal}	glob
158  * @return {String[]} array of file's absolute paths or undefined if the dir is invalid
159  */
160 File.glob = function(dir, glob){
161 	//Checks for glob pattern is a Regular Expression literal or undefined
162 	if (typeof glob == 'undefined') {
163 		log(" The file glob expression is not defined.", 5, instance.LOG);
164 		return undefined;
165 	}
166 	//Check if	directory is valid 
167 	var dirPath = new java.io.File(dir);
168 	if (typeof dir == 'undefined' || !dirPath.exists()) {
169 		log(" No such file or directory : " + dir + ". ", 5, instance.LOG);
170 		return undefined;
171 	}
172 	
173 	//Check the specified File is a directory
174 	if (!dirPath.isDirectory()) {
175 		log(dir + " is not a directory!", 5, instance.LOG);
176 		return undefined;
177 	}
178 	
179 	var fileList = [];
180 	//Collect array of all Files
181 	var fileTokens = dirPath.listFiles();
182 	var count = 0;
183 	for (var i = 0; i < fileTokens.length; i++) {
184 		var _currentFile = fileTokens[i];
185 		//Only files to be filtered for given pattern i.e @glob argument
186 		if (_currentFile.isFile()) {
187 			if (_currentFile.getName().search(glob) != -1) {
188 				// adding the matched file's absolute path to the array
189 				fileList[count] = _currentFile.getAbsolutePath();
190 				count++;
191 			}
192 		}
193 	}
194 	log("Found	" + count + " files which match '" + glob + "' glob literal", 0, instance.LOG);
195 	return fileList;
196 };
197 
198 /**
199  * Creates a file, including all containing directories as necessary.
200  * The path to the file must be absolute, and must be contained within the Sentinel directory
201  * /var, or /tmp (on Windows, since there is no standard "variable data" area, create a.
202  * @param {Object} file	The file to create
203  * @return {Boolean}	False if the file could not be created.
204  */
205 File.create = function(file){
206 	if (typeof file == "undefined" ||
207 	(file.substr(0, instance.CONFIG.esecDir.length + 4) != instance.CONFIG.esecDir + "data" &&
208 	file.substr(0, instance.CONFIG.esecDir.length + 3) != instance.CONFIG.esecDir + "log")) {
209 		return false;
210 	}
211 	var dir = file.substr(0, file.lastIndexOf("/"));
212 	var success = (new java.io.File(dir)).mkdirs();
213 	if (!success) {
214 		return false;
215 	}
216 	success = (new java.io.File(file)).createNewFile();
217 	if (!success) {
218 		return false;
219 	}
220 	return true;	
221 }
222 
223 
224 /**
225  * Renames a file.
226  * The path to the files must be absolute and must be contained within the ESEC_HOME directory.
227  * @param {String} fromName - soure file name
228  * @param {String} toName - destination file name
229  * @return {Boolean} status of file rename.
230  */
231 File.rename = function(fromName, toName){
232 	if (typeof fromName == "undefined" ||
233 	(fromName.substr(0, instance.CONFIG.esecDir.length + 4) != instance.CONFIG.esecDir + "data" &&
234 	fromName.substr(0, instance.CONFIG.esecDir.length + 3) != instance.CONFIG.esecDir + "log")) {
235 		return false;
236 	}
237 	var finalFlag = false;
238 	var flag = FileUtil.renameFile(fromName, toName);
239 	log("FileUtil.renameFile(..) returns " + flag, 0, instance.LOG);
240 	if (flag === 0) {
241 		finalFlag = true;
242 	}	else {
243 		log("Could not rename the file " + fromName, 5, instance.LOG);
244 		finalFlag = false;
245 	}
246 	return finalFlag;
247 };
248 
249 /**
250  * Deletes a file.
251  * The path to the files must be absolute and must be contained within the ESEC_HOME directory.
252  * @param {String} filename
253  * @return {Boolean} status of file remove
254  */
255 File.remove = function(fileName) {
256 	if (typeof fileName == "undefined" ||
257 			(fileName.substr(0, instance.CONFIG.esecDir.length + 4) != instance.CONFIG.esecDir + "data" &&
258 			fileName.substr(0, instance.CONFIG.esecDir.length + 3) != instance.CONFIG.esecDir + "log")) {
259 		return false;
260 	}
261 	var finalFlag = false;
262 	var flag = FileUtil.deleteFile(fileName);
263 	log("FileUtil.deleteFile(..) returns " + flag, 0, instance.LOG);
264 	if (flag === 0) {
265 		finalFlag = true;
266 	}	else {
267 		log("Could not delete the file " + fileName, 5, instance.LOG);
268 		finalFlag = false;
269 	}
270 	return finalFlag;
271 };
272 
273 /**
274  * Gets the time the file was last modified, in milliseconds since midnight Jan 1 '70
275  * @param {Object} fileName  The name of the file to get the mod time of
276  * @return {Number}  Number of milliseconds since midnight Jan 1 '70
277  */
278 File.modTime = function(fileName) {
279 	if (typeof fileName == "undefined" ||
280 			(fileName.substr(0, instance.CONFIG.esecDir.length + 4) != instance.CONFIG.esecDir + "data" &&
281 			fileName.substr(0, instance.CONFIG.esecDir.length + 3) != instance.CONFIG.esecDir + "log")) {
282 		return 0;
283 	}
284 	var file = new java.io.File(fileName);
285 	return file.lastModified();
286 }
287