001: /*
002: * JEditHistoryModelSaver.java - Handles services.xml files in plugins
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 2006 Matthieu Casanova
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License
010: * as published by the Free Software Foundation; either version 2
011: * of the License, or any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
021: */
022: package org.gjt.sp.jedit.gui;
023:
024: import org.gjt.sp.util.Log;
025: import org.gjt.sp.util.IOUtilities;
026: import org.gjt.sp.jedit.MiscUtilities;
027: import org.gjt.sp.jedit.jEdit;
028:
029: import java.io.*;
030: import java.nio.charset.Charset;
031: import java.nio.charset.CharacterCodingException;
032: import java.util.*;
033:
034: /**
035: * @author Matthieu Casanova
036: * @version $Id: FoldHandler.java 5568 2006-07-10 20:52:23Z kpouer $
037: */
038: public class JEditHistoryModelSaver implements HistoryModelSaver {
039: //{{{ load() method
040: public Map<String, HistoryModel> load(
041: Map<String, HistoryModel> models) {
042: String settingsDirectory = jEdit.getSettingsDirectory();
043: if (settingsDirectory == null)
044: return models;
045:
046: history = new File(MiscUtilities.constructPath(
047: settingsDirectory, "history"));
048: if (!history.exists())
049: return models;
050:
051: historyModTime = history.lastModified();
052:
053: Log.log(Log.MESSAGE, HistoryModel.class, "Loading history");
054:
055: if (models == null)
056: models = Collections
057: .synchronizedMap(new HashMap<String, HistoryModel>());
058:
059: BufferedReader in = null;
060: try {
061: // Try loading with UTF-8 and fallback to the system
062: // default encoding to load a history which was made by
063: // an old version as well.
064: try {
065: // Pass the decoder explicitly to report a decode error
066: // as an exception instead of replacing with \xFFFD.
067: in = new BufferedReader(new InputStreamReader(
068: new FileInputStream(history), Charset.forName(
069: "UTF-8").newDecoder()));
070: models.putAll(loadFromReader(in));
071: } catch (CharacterCodingException e) {
072: // It seems to be made by an old version of jEdit.
073: in.close();
074: Log
075: .log(
076: Log.MESSAGE,
077: HistoryModel.class,
078: "Failed to load history with UTF-8."
079: + " Fallbacking to the system default encoding.");
080:
081: in = new BufferedReader(new FileReader(history));
082: models.putAll(loadFromReader(in));
083: }
084: } catch (FileNotFoundException fnf) {
085: //Log.log(Log.DEBUG,HistoryModel.class,fnf);
086: } catch (IOException io) {
087: Log.log(Log.ERROR, HistoryModel.class, io);
088: } finally {
089: IOUtilities.closeQuietly(in);
090: }
091: return models;
092: } //}}}
093:
094: //{{{ save() method
095: public boolean save(Map<String, HistoryModel> models) {
096: Log.log(Log.MESSAGE, HistoryModel.class, "Saving history");
097: File file1 = new File(MiscUtilities.constructPath(jEdit
098: .getSettingsDirectory(), "#history#save#"));
099: File file2 = new File(MiscUtilities.constructPath(jEdit
100: .getSettingsDirectory(), "history"));
101: if (file2.exists() && file2.lastModified() != historyModTime) {
102: Log.log(Log.WARNING, HistoryModel.class, file2
103: + " changed on disk; will not save history");
104: return false;
105: }
106:
107: jEdit.backupSettingsFile(file2);
108:
109: String lineSep = System.getProperty("line.separator");
110:
111: BufferedWriter out = null;
112:
113: try {
114: out = new BufferedWriter(new OutputStreamWriter(
115: new FileOutputStream(file1), "UTF-8"));
116:
117: if (models != null) {
118: Collection<HistoryModel> values = models.values();
119: for (HistoryModel model : values) {
120: if (model.getSize() == 0)
121: continue;
122:
123: out.write('[');
124: out.write(MiscUtilities.charsToEscapes(model
125: .getName(), TO_ESCAPE));
126: out.write(']');
127: out.write(lineSep);
128:
129: for (int i = 0; i < model.getSize(); i++) {
130: out.write(MiscUtilities.charsToEscapes(model
131: .getItem(i), TO_ESCAPE));
132: out.write(lineSep);
133: }
134: }
135: }
136:
137: out.close();
138:
139: /* to avoid data loss, only do this if the above
140: * completed successfully */
141: file2.delete();
142: file1.renameTo(file2);
143: } catch (IOException io) {
144: Log.log(Log.ERROR, HistoryModel.class, io);
145: } finally {
146: IOUtilities.closeQuietly(out);
147: }
148:
149: historyModTime = file2.lastModified();
150: return true;
151: } //}}}
152:
153: //{{{ Private members
154: private static final String TO_ESCAPE = "\r\n\t\\\"'[]";
155: private static File history;
156: private static long historyModTime;
157:
158: //{{{ loadFromReader() method
159: private static Map<String, HistoryModel> loadFromReader(
160: BufferedReader in) throws IOException {
161: Map<String, HistoryModel> result = new HashMap<String, HistoryModel>();
162:
163: HistoryModel currentModel = null;
164: String line;
165:
166: while ((line = in.readLine()) != null) {
167: if (line.length() > 0 && line.charAt(0) == '['
168: && line.charAt(line.length() - 1) == ']') {
169: if (currentModel != null) {
170: result.put(currentModel.getName(), currentModel);
171: }
172:
173: String modelName = MiscUtilities.escapesToChars(line
174: .substring(1, line.length() - 1));
175: currentModel = new HistoryModel(modelName);
176: } else if (currentModel == null) {
177: throw new IOException("History data starts"
178: + " before model name");
179: } else {
180: currentModel.addElement(MiscUtilities
181: .escapesToChars(line));
182: }
183: }
184:
185: if (currentModel != null) {
186: result.put(currentModel.getName(), currentModel);
187: }
188:
189: return result;
190: } //}}}
191:
192: //}}}
193:
194: }
|