/** * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * https://opensso.dev.java.net/public/CDDLv1.0.html or * opensso/legal/CDDLv1.0.txt * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at opensso/legal/CDDLv1.0.txt. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * $Id: FileEditor.java,v 1.2 2008/06/25 05:51:29 qcheng Exp $ * */ package com.sun.identity.install.tools.util; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.OutputStreamWriter; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeSet; /** * Class that provides functionality to match the "lines" with specified * pattern and remove them from the specified file. * */ public class FileEditor { public FileEditor(String fileName) { setFileName(fileName); } /** * * @param matchPatterns * a Set of DeletePatterns * @return true if all the patterns were found and deleted. False if some * patterns were not found. In such cases no changes are made to * the file. * @throws Exception */ public boolean deleteLines(Set matchPatterns) throws Exception { boolean success = false; Map patternOccurrances = getPatternOccurences(matchPatterns); if (patternOccurrances.size() == matchPatterns.size()) { TreeSet removeLines = addSuccessiveDeleteLines(matchPatterns, patternOccurrances); success = deleteLineNumbers(removeLines); } return success; } public boolean deleteLines(DeletePattern pattern) throws Exception { Set matchPatterns = new HashSet(); matchPatterns.add(pattern); Map patternOccurrances = getPatternOccurences(matchPatterns); boolean success = false; if (patternOccurrances.size() == 1) { // Just one match should be // found TreeSet removeLines = addSuccessiveDeleteLines(matchPatterns, patternOccurrances); success = deleteLineNumbers(removeLines); } return success; } private TreeSet addSuccessiveDeleteLines(Set matchPatterns, Map patternOccurrances) { TreeSet removeLines = new TreeSet(patternOccurrances.values()); Iterator iter = matchPatterns.iterator(); while (iter.hasNext()) { DeletePattern dp = (DeletePattern) iter.next(); Integer lineNumber = (Integer) patternOccurrances.get(dp .getPattern()); int numSuccessiveLines = dp.getNumberOfSuccessiveLines(); for (int i = 1; i <= numSuccessiveLines; i++) { removeLines.add(new Integer(lineNumber.intValue() + i)); } } return removeLines; } private boolean deleteLineNumbers(TreeSet lineNumbers) throws Exception { // Get the line numbers and sort them using TreeSet Debug.log("FileEditor.deleteLineNumbers() - Lines that " + "will be skipped: " + lineNumbers); TreeSet removeLineNumbers = new TreeSet(lineNumbers); LineNumberReader reader = null; BufferedWriter writer = null; try { FileInputStream fi = new FileInputStream(getFileName()); InputStreamReader ir = new InputStreamReader(fi); reader = new LineNumberReader(ir); reader.setLineNumber(0); FileOutputStream fo = new FileOutputStream(getTempFileName()); OutputStreamWriter ow = new OutputStreamWriter(fo); writer = new BufferedWriter(ow); String lineData = null; Integer removeLine = (Integer) removeLineNumbers.first(); while ((lineData = reader.readLine()) != null) { removeLine = verifyAndDeleteLine(reader, writer, lineData, removeLineNumbers, removeLine); } } catch (Exception e) { Debug.log("FileEditor.removeLines() - Exception occurred " + "while removing lines from file. " + getFileName(), e); throw e; } finally { if (reader != null) { try { reader.close(); } catch (IOException ie) { // Ignore } } if (writer != null) { try { writer.flush(); writer.close(); } catch (IOException ie) { } } } // Delete the original file and rename temp file as original File originalFile = new File(getFileName()); originalFile.delete(); File tempFile = new File(getTempFileName()); tempFile.renameTo(originalFile); return removeLineNumbers.isEmpty(); // If empty then successful } private Integer verifyAndDeleteLine(LineNumberReader reader, BufferedWriter writer, String lineData, TreeSet removeLineNumbers, Integer removeLine) throws IOException { Integer nextLineToRemove = removeLine; int lineNumber = reader.getLineNumber(); if (!removeLineNumbers.isEmpty() && removeLine.intValue() == lineNumber) { // Determine next line to skip from being written to file Debug.log("FileEditor.skipLinesAndCreateTempFile() - " + "Skipping line[" + lineNumber + "]=" + lineData); removeLineNumbers.remove(removeLine); if (!removeLineNumbers.isEmpty()) { nextLineToRemove = (Integer) removeLineNumbers.first(); } } else { writer.write(lineData + LINE_SEP); } return nextLineToRemove; } public Map getPatternOccurences(Set matchPatterns) throws Exception { boolean matchFound = false; // A Map which stores key=value as // pattern-string=line-number-to-be-removed Map matchedLines = new HashMap(); LineNumberReader reader = null; try { FileReader fr = new FileReader(getFileName()); reader = new LineNumberReader(fr); reader.setLineNumber(0); String lineData = null; while ((lineData = reader.readLine()) != null) { int lineNumber = reader.getLineNumber(); matchAndAddLineNumbers(matchPatterns, lineData, lineNumber, matchedLines); } } catch (Exception e) { Debug.log("FileEditor.getPatternOccurences() - Exception " + "occurred while searching for patterns. ", e); throw e; } finally { if (reader != null) { try { reader.close(); } catch (IOException ie) { // Ignore } } } return matchedLines; } private void matchAndAddLineNumbers(Set matchPatterns, String lineData, int lineNumber, Map matchedLines) { boolean isFound = false; Iterator iter = matchPatterns.iterator(); while (iter.hasNext() && !isFound) { // Iterate through all active patterns and see if they are present // in line MatchPattern matchPattern = (MatchPattern) iter.next(); if (matchPattern.isActive() && matchPattern.isPresent(lineData)) { Debug.log("FileEditor.matchAndAddLineNumbers() - Found " + "pattern " + matchPattern); // Add the pattern & line number to the Map. Integer number = new Integer(lineNumber); matchedLines.put(matchPattern.getPattern(), number); if (!matchPattern.isMatchForLastOccurranceInFile()) { // We don't want this match to be active anymore as the // first occurance is already found. matchPattern.setIsActiveFlag(false); } isFound = true; } } } private void printMap(Map map) { Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry me = (Map.Entry) iter.next(); Debug.log("FileEditor.printMap() - " + me.getKey() + "=" + me.getValue()); } } private String getTempFileName() { return getFileName() + STR_TEMP_FILE_SUFFIX; } private String getFileName() { return fileName; } private void setFileName(String fileName) { this.fileName = fileName; } private String fileName; public static final String LINE_SEP = System.getProperty("line.separator"); public static final String STR_TEMP_FILE_SUFFIX = ".tmp"; }