/* * JEditHistoryModelSaver.java - * :tabSize=4:indentSize=4:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 2006 Matthieu Casanova * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gjt.sp.jedit.gui; import org.gjt.sp.util.Log; import org.gjt.sp.util.IOUtilities; import org.gjt.sp.util.StandardUtilities; import org.gjt.sp.jedit.MiscUtilities; import org.gjt.sp.jedit.jEdit; import java.io.*; import java.nio.charset.Charset; import java.nio.charset.CharacterCodingException; import java.util.*; /** Handles loading and saving of the "history" files. * * A history file is .ini format and stores historymodels for all * named historytextfields, separately but in the same file. * * @author Matthieu Casanova * @version $Id: FoldHandler.java 5568 2006-07-10 20:52:23Z kpouer $ */ public class JEditHistoryModelSaver implements HistoryModelSaver { //{{{ load() method public Map<String, HistoryModel> load(Map<String, HistoryModel> models) { String settingsDirectory = jEdit.getSettingsDirectory(); if(settingsDirectory == null) return models; history = new File(MiscUtilities.constructPath( settingsDirectory,"history")); if(!history.exists()) return models; historyModTime = history.lastModified(); Log.log(Log.MESSAGE,HistoryModel.class,"Loading history"); if(models == null) models = Collections.synchronizedMap(new HashMap<String, HistoryModel>()); BufferedReader in = null; try { // Try loading with UTF-8 and fallback to the system // default encoding to load a history which was made by // an old version as well. try { // Pass the decoder explicitly to report a decode error // as an exception instead of replacing with \xFFFD. in = new BufferedReader(new InputStreamReader( new FileInputStream(history), Charset.forName("UTF-8").newDecoder())); models.putAll(loadFromReader(in)); } catch(CharacterCodingException e) { // It seems to be made by an old version of jEdit. in.close(); Log.log(Log.MESSAGE,HistoryModel.class, "Failed to load history with UTF-8." + " Fallbacking to the system default encoding."); in = new BufferedReader(new FileReader(history)); models.putAll(loadFromReader(in)); } } catch(FileNotFoundException fnf) { //Log.log(Log.DEBUG,HistoryModel.class,fnf); } catch(IOException io) { Log.log(Log.ERROR,HistoryModel.class,io); } finally { IOUtilities.closeQuietly((Closeable)in); } return models; } //}}} //{{{ save() method public boolean save(Map<String, HistoryModel> models) { Log.log(Log.MESSAGE,HistoryModel.class,"Saving history"); File file1 = new File(MiscUtilities.constructPath( jEdit.getSettingsDirectory(), "#history#save#")); File file2 = new File(MiscUtilities.constructPath( jEdit.getSettingsDirectory(), "history")); if(file2.exists() && file2.lastModified() != historyModTime) { Log.log(Log.WARNING,HistoryModel.class,file2 + " changed on disk; will not save history"); return false; } jEdit.backupSettingsFile(file2); String lineSep = System.getProperty("line.separator"); BufferedWriter out = null; try { out = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(file1), "UTF-8")); if(models != null) { Collection<HistoryModel> values = models.values(); for (HistoryModel model : values) { if(model.getSize() == 0) continue; out.write('['); out.write(StandardUtilities.charsToEscapes( model.getName(),TO_ESCAPE)); out.write(']'); out.write(lineSep); for(int i = 0; i < model.getSize(); i++) { out.write(StandardUtilities.charsToEscapes( model.getItem(i), TO_ESCAPE)); out.write(lineSep); } } } out.close(); /* to avoid data loss, only do this if the above * completed successfully */ file2.delete(); file1.renameTo(file2); } catch(IOException io) { Log.log(Log.ERROR,HistoryModel.class,io); } finally { IOUtilities.closeQuietly((Closeable)out); } historyModTime = file2.lastModified(); return true; } //}}} //{{{ Private members private static final String TO_ESCAPE = "\r\n\t\\\"'[]"; private static File history; private static long historyModTime; //{{{ loadFromReader() method private static Map<String, HistoryModel> loadFromReader(BufferedReader in) throws IOException { Map<String, HistoryModel> result = new HashMap<String, HistoryModel>(); HistoryModel currentModel = null; String line; while((line = in.readLine()) != null) { if(line.length() > 0 && line.charAt(0) == '[' && line.charAt(line.length() - 1) == ']') { if(currentModel != null) { result.put(currentModel.getName(), currentModel); } String modelName = MiscUtilities .escapesToChars(line.substring( 1,line.length() - 1)); currentModel = new HistoryModel( modelName); } else if(currentModel == null) { throw new IOException("History data starts" + " before model name"); } else { currentModel.addElement(MiscUtilities .escapesToChars(line)); } } if(currentModel != null) { result.put(currentModel.getName(),currentModel); } return result; } //}}} //}}} }