PageRenderTime 71ms CodeModel.GetById 19ms RepoModel.GetById 6ms app.codeStats 0ms

/bundles/plugins-trunk/Sessions/sessions/Session.java

#
Java | 585 lines | 381 code | 74 blank | 130 comment | 30 complexity | 19fbb9f2b034a551fe5242ec44fba3e4 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * Session.java - represents a jEdit session
  3. * Copyright (c) 2001 Dirk Moebius
  4. * Copyright (c) 2008 Steve Jakob
  5. *
  6. * :tabSize=4:indentSize=4:noTabs=false:maxLineLen=0:
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. package sessions;
  23. import java.io.BufferedReader;
  24. import java.io.BufferedWriter;
  25. import java.io.File;
  26. import java.io.FileInputStream;
  27. import java.io.FileWriter;
  28. import java.io.IOException;
  29. import java.io.InputStreamReader;
  30. import java.util.Enumeration;
  31. import java.util.Hashtable;
  32. import java.util.Iterator;
  33. import java.util.Vector;
  34. import org.gjt.sp.jedit.Buffer;
  35. import org.gjt.sp.jedit.EditBus;
  36. import org.gjt.sp.jedit.View;
  37. import org.gjt.sp.jedit.jEdit;
  38. import org.gjt.sp.util.Log;
  39. import org.gjt.sp.util.XMLUtilities;
  40. import org.xml.sax.Attributes;
  41. import org.xml.sax.InputSource;
  42. import org.xml.sax.SAXException;
  43. import org.xml.sax.helpers.DefaultHandler;
  44. public class Session implements Cloneable
  45. {
  46. /** Session Property name for Session base directory */
  47. public static final String BASE_DIRECTORY = "basedir";
  48. /** Session Property name for Session default edit mode */
  49. public static final String DEFAULT_MODE = "mode";
  50. private String name;
  51. private String filename;
  52. private String currentFile;
  53. private Hashtable properties, sessionFiles;
  54. public Session(String name)
  55. {
  56. setName(name);
  57. this.sessionFiles = new Hashtable();
  58. this.properties = new Hashtable();
  59. }
  60. public String getName()
  61. {
  62. return name;
  63. }
  64. public void setName(String name)
  65. {
  66. this.name = name;
  67. this.filename = SessionManager.createSessionFileName(name);
  68. }
  69. /**
  70. * Rename this session. This changes both the logical name and the filename.
  71. * @param newName The new name for the session.
  72. * @return <code>true</code> if the rename succeeds, <code>false</code> otherwise.
  73. */
  74. public boolean rename(String newName)
  75. {
  76. String oldName = this.name;
  77. File oldFile = new File(this.filename);
  78. File newFile = new File(SessionManager.createSessionFileName(newName));
  79. if (oldFile.renameTo(newFile) == false)
  80. {
  81. // rename failed, so ...
  82. return false;
  83. }
  84. setName(newName);
  85. // Re-save so that the file contains the updated Session name
  86. try {
  87. saveXML();
  88. } catch (IOException ioe) {
  89. setName(oldName);
  90. return false;
  91. }
  92. return true;
  93. }
  94. public String getFilename()
  95. {
  96. return filename;
  97. }
  98. public String toString()
  99. {
  100. return name;
  101. }
  102. public void setCurrentFile(String file)
  103. {
  104. if(hasFile(file))
  105. currentFile = file;
  106. else
  107. Log.log(Log.DEBUG, this, "setCurrentFile: session " + name + ": doesn't contain file " + file + " - use addFile() first.");
  108. }
  109. public String getCurrentFile()
  110. {
  111. return currentFile;
  112. }
  113. /**
  114. * Get a session property.
  115. *
  116. * @return the session property value, of null if the specified key
  117. * cannot be found.
  118. */
  119. public String getProperty(String key)
  120. {
  121. Object value = properties.get(key);
  122. return value == null ? null : value.toString();
  123. }
  124. /**
  125. * Set a session property.
  126. * This sends out a SessionPropertyChanged message on EditBus.
  127. * Note that having a value of <code>null</code> is the same as
  128. * removeProperty(key), in which case a SessionPropertyRemoved
  129. * message is sent out on EditBus.
  130. *
  131. * @throws NullPointerException if key is null.
  132. */
  133. public void setProperty(String key, String value)
  134. {
  135. if(value != null)
  136. {
  137. Object oldValue = properties.put(key, value);
  138. EditBus.send(new SessionPropertyChanged(
  139. SessionManager.getInstance(), this, key,
  140. oldValue != null ? oldValue.toString() : null, value));
  141. }
  142. else
  143. removeProperty(key);
  144. }
  145. // being nice to developers: some convenience methods for storing/retrieving primitives
  146. public int getIntProperty(String key, int defaultValue) { return ParseUtilities.toInt(getProperty(key), defaultValue); }
  147. public long getLongProperty(String key, long defaultValue) { return ParseUtilities.toLong(getProperty(key), defaultValue); }
  148. public boolean getBooleanProperty(String key, boolean defaultValue) { return ParseUtilities.toBoolean(getProperty(key), defaultValue); }
  149. public float getFloatProperty(String key, float defaultValue) { return ParseUtilities.toFloat(getProperty(key), defaultValue); }
  150. public double getDoubleProperty(String key, double defaultValue) { return ParseUtilities.toDouble(getProperty(key), defaultValue); }
  151. public String getProperty(String key, String defaultValue) { String s = getProperty(key); return s != null ? s : defaultValue; }
  152. public void setIntProperty(String key, int value) { setProperty(key, String.valueOf(value)); }
  153. public void setLongProperty(String key, long value) { setProperty(key, String.valueOf(value)); }
  154. public void setBooleanProperty(String key, boolean value) { setProperty(key, String.valueOf(value)); }
  155. public void setFloatProperty(String key, float value) { setProperty(key, String.valueOf(value)); }
  156. public void setDoubleProperty(String key, double value) { setProperty(key, String.valueOf(value)); }
  157. /**
  158. * Remove a session property.
  159. * If the property was part of this session, a SessionPropertyRemoved
  160. * message is sent out on EditBus. If the session didn't contain
  161. * the property, nothing is sent.
  162. *
  163. * @throws NullPointerException if key is null.
  164. */
  165. public void removeProperty(String key)
  166. {
  167. if(properties.containsKey(key))
  168. {
  169. Object oldValue = properties.remove(key);
  170. EditBus.send(new SessionPropertyRemoved(
  171. SessionManager.getInstance(), this, key,
  172. oldValue != null ? oldValue.toString() : null));
  173. }
  174. }
  175. public boolean hasFile(String file)
  176. {
  177. return sessionFiles.containsKey(file);
  178. }
  179. /**
  180. * Returns a <code>java.util.Enumeration</code> containing
  181. * <code>java.io.File</code> objects corresponding to the files
  182. * managed by this <code>Session</code> object.
  183. */
  184. public Enumeration getAllFiles()
  185. {
  186. return sessionFiles.elements();
  187. }
  188. /**
  189. * Returns a <code>java.util.Enumeration</code> containing
  190. * <code>String</code> objects corresponding to the names of the files
  191. * managed by this <code>Session</code> object.
  192. */
  193. public Enumeration getAllFilenames()
  194. {
  195. return sessionFiles.keys();
  196. }
  197. /**
  198. * Loads and opens the session.
  199. * The session is loaded from the XML file in the sessions repository,
  200. * then the files of the session are opened.
  201. *
  202. * @see #open(org.gjt.sp.jedit.View, boolean)
  203. * @param view where to display error message boxes.
  204. * @return true if the session was loaded successfully and all buffers
  205. * have been opened.
  206. */
  207. public boolean open(View view)
  208. {
  209. return open(view, true);
  210. }
  211. /**
  212. * Loads and optionally opens the session.
  213. * The session is loaded from the XML file in the sessions repository,
  214. * then the files of the session are opened.
  215. *
  216. * @param view where to display error message boxes.
  217. * @param openFiles whether or not to open all the session files in addition
  218. * to loading and parsing the XML file (with its custom properties).
  219. * @return true if the session was loaded successfully and all buffers
  220. * have been opened.
  221. */
  222. public boolean open(View view, boolean openFiles)
  223. {
  224. Log.log(Log.DEBUG, this, "open: name=" + name);
  225. try
  226. {
  227. loadXML();
  228. }
  229. catch (IOException io)
  230. {
  231. Log.log(Log.ERROR, this, io);
  232. SessionManager.showErrorLater(view, "ioerror", new Object[] { io.getMessage() });
  233. return false;
  234. }
  235. catch (Exception e)
  236. {
  237. // this is probably a xml parse exception
  238. Log.log(Log.ERROR, this, e);
  239. SessionManager.showErrorLater(view, "sessions.manager.error.load", new Object[] { name, e.getMessage() });
  240. return false;
  241. }
  242. if (openFiles)
  243. {
  244. // open session files:
  245. Iterator it = sessionFiles.values().iterator();
  246. while(it.hasNext())
  247. {
  248. SessionFile sf = (SessionFile)it.next();
  249. Hashtable props = sf.getBufferProperties();
  250. jEdit.openFile(view, null, sf.getPath(), false, props);
  251. }
  252. // open session's recent buffer:
  253. if(currentFile != null)
  254. {
  255. Buffer buffer = jEdit.getBuffer(currentFile);
  256. if(buffer != null)
  257. view.setBuffer(buffer);
  258. }
  259. }
  260. return true;
  261. }
  262. /**
  263. * Saves the session.
  264. *
  265. * @param view The view the session is being saved from.
  266. * @return true, if the session was saved successfully,
  267. * false if an IOException occurred.
  268. */
  269. public boolean save(View view)
  270. {
  271. Log.log(Log.DEBUG, this, "save: name=" + name);
  272. if (view != null)
  273. view.getEditPane().saveCaretInfo();
  274. // Right now, the session's file list is cleared and filled again with
  275. // the current list of open jEdit buffers, but this behavior could be
  276. // changed in the future...
  277. sessionFiles.clear();
  278. for(Buffer buffer = jEdit.getFirstBuffer(); buffer != null; buffer = buffer.getNext())
  279. if(!buffer.isUntitled())
  280. addFile(buffer.getPath(), buffer.getStringProperty(Buffer.ENCODING));
  281. if(view != null)
  282. currentFile = view.getBuffer().getPath();
  283. try
  284. {
  285. saveXML();
  286. }
  287. catch (IOException io) {
  288. Log.log(Log.ERROR, this, io);
  289. SessionManager.showErrorLater(view, "ioerror", new Object[] { io.getMessage() });
  290. return false;
  291. }
  292. return true;
  293. }
  294. /**
  295. * Has the the list of opened files changed?
  296. *
  297. * @return <code>true</code> if the file list has not changed
  298. * since the previous load/update,
  299. * <code>false</code> if some file(s) have been opened/closed
  300. */
  301. public boolean hasFileListChanged()
  302. {
  303. Vector currentFiles = new Vector();
  304. for(Buffer buffer = jEdit.getFirstBuffer(); buffer != null; buffer = buffer.getNext())
  305. if(!buffer.isUntitled())
  306. currentFiles.addElement(buffer.getPath());
  307. Vector allFiles = new Vector(sessionFiles.values());
  308. if (allFiles.equals(currentFiles))
  309. return false;
  310. return true;
  311. }
  312. /**
  313. * Add a file to the session's file list using the default character encoding.
  314. */
  315. public void addFile(String file)
  316. {
  317. if(hasFile(file))
  318. Log.log(Log.DEBUG, this, "addFile: session " + name + ": already contains file " + file + " - not added.");
  319. else
  320. addFile(file, jEdit.getProperty("buffer.encoding",
  321. System.getProperty("file.encoding")));
  322. }
  323. /**
  324. * Add a file to the session's file list using the supplied character encoding.
  325. */
  326. public void addFile(String file, String encoding)
  327. {
  328. if(hasFile(file))
  329. Log.log(Log.DEBUG, this, "addFile: session " + name + ": already contains file " + file + " - not added.");
  330. else
  331. sessionFiles.put(file, new SessionFile(file, encoding));
  332. }
  333. /**
  334. * Clears the session's contents: forgets all open files and properties,
  335. * and the name of the current file.
  336. */
  337. public void clear()
  338. {
  339. sessionFiles.clear();
  340. properties.clear();
  341. currentFile = null;
  342. }
  343. public Object clone()
  344. {
  345. return getClone();
  346. }
  347. public Session getClone()
  348. {
  349. Session clone = new Session(this.name);
  350. clone.sessionFiles = (Hashtable) this.sessionFiles.clone();
  351. clone.properties = (Hashtable) this.properties.clone();
  352. return clone;
  353. }
  354. /**
  355. * Loads the session, but does not open any files in jEdit.
  356. */
  357. public void loadXML() throws Exception
  358. {
  359. Log.log(Log.DEBUG, this, "loadXML: name=" + name + " filename=" + filename);
  360. clear();
  361. // Reader reader = new BufferedReader(new FileReader(filename));
  362. XMLUtilities.parseXML(new FileInputStream(filename), new SessionXmlHandler());
  363. //XmlParser parser = new XmlParser();
  364. //parser.setHandler(new SessionXmlHandler(parser));
  365. //parser.parse(null, null, reader);
  366. }
  367. /**
  368. * Saves the session.
  369. */
  370. public void saveXML() throws IOException
  371. {
  372. Log.log(Log.DEBUG, this, "saveXML: name=" + name + " filename=" + filename);
  373. BufferedWriter out = new BufferedWriter(new FileWriter(filename));
  374. // write header
  375. out.write("<?xml version=\"1.0\"?>");
  376. out.newLine();
  377. out.write("<!DOCTYPE SESSION SYSTEM \"session.dtd\">");
  378. out.newLine();
  379. out.newLine();
  380. // write session name
  381. out.write("<SESSION name=\"");
  382. out.write(name);
  383. out.write("\">");
  384. out.newLine();
  385. // write files
  386. out.write(" <FILES>");
  387. out.newLine();
  388. saveFiles(out);
  389. out.write(" </FILES>");
  390. out.newLine();
  391. out.newLine();
  392. // write properties
  393. out.write(" <PROPERTIES>");
  394. out.newLine();
  395. saveProperties(out);
  396. out.write(" </PROPERTIES>");
  397. out.newLine();
  398. out.write("</SESSION>");
  399. out.newLine();
  400. out.close();
  401. }
  402. private void saveFiles(BufferedWriter out) throws IOException
  403. {
  404. Enumeration myEnum = sessionFiles.elements();
  405. while(myEnum.hasMoreElements())
  406. {
  407. SessionFile sf = (SessionFile)myEnum.nextElement();
  408. String filename = sf.getPath().replace('\\','/');
  409. out.write(" <FILE filename=\"");
  410. out.write(ParseUtilities.encodeXML(filename));
  411. out.write('"');
  412. if(filename.equals(getCurrentFile().replace('\\','/')))
  413. out.write(" isCurrent=\"true\"");
  414. // Write character encoding info, carat position
  415. Buffer buff = jEdit.getBuffer(filename);
  416. if (buff != null)
  417. {
  418. String encoding = buff.getStringProperty(Buffer.ENCODING);
  419. if (encoding != null && encoding.length() > 0)
  420. out.write(" encoding=\"" + encoding + "\"");
  421. Integer carat = new Integer(buff.getIntegerProperty(
  422. Buffer.CARET, 0));
  423. out.write(" carat=\"" + carat.toString() + "\"");
  424. }
  425. out.write("/>");
  426. out.newLine();
  427. }
  428. }
  429. private void saveProperties(BufferedWriter out) throws IOException
  430. {
  431. Enumeration myEnum = properties.keys();
  432. while(myEnum.hasMoreElements())
  433. {
  434. String key = myEnum.nextElement().toString();
  435. String value = getProperty(key);
  436. Log.log(Log.DEBUG, this, "Writing PROP: " + key);
  437. out.write(" <PROP key=\"");
  438. out.write(ParseUtilities.encodeXML(key));
  439. out.write('"');
  440. // if value is null, don't write a value="" element:
  441. if(value != null)
  442. {
  443. out.write(" value=\"");
  444. out.write(ParseUtilities.encodeXML(value));
  445. out.write('"');
  446. }
  447. out.write("/>");
  448. out.newLine();
  449. }
  450. }
  451. private class SessionXmlHandler extends DefaultHandler
  452. {
  453. boolean atStart = false;
  454. SessionXmlHandler()
  455. {
  456. }
  457. public void startDocument() throws SAXException
  458. {
  459. super.startDocument();
  460. atStart = true;
  461. }
  462. public void startElement(String uri, String localName, String name, Attributes attributes)
  463. throws SAXException
  464. {
  465. if (atStart)
  466. {
  467. if (localName.equalsIgnoreCase("session"))
  468. {
  469. atStart = false;
  470. return;
  471. }
  472. else
  473. {
  474. throw new SAXException("DOCTYPE must be SESSION");
  475. }
  476. }
  477. if (name.equalsIgnoreCase("prop"))
  478. {
  479. String key = attributes.getValue("key");
  480. String value = attributes.getValue("value");
  481. properties.put(key, value);
  482. }
  483. else if (name.equalsIgnoreCase("file"))
  484. {
  485. String filePath = attributes.getValue("filename");
  486. String encoding = attributes.getValue("encoding");
  487. boolean isCurrent = "true".equalsIgnoreCase(attributes.getValue("isCurrent"));
  488. addFile(filePath, encoding);
  489. if (isCurrent)
  490. {
  491. setCurrentFile(filePath);
  492. }
  493. }
  494. super.startElement(uri, localName, name, attributes);
  495. }
  496. public InputSource resolveEntity(String publicId, String systemId) throws IOException
  497. {
  498. if (systemId.endsWith("session.dtd"))
  499. return new InputSource(new BufferedReader(new InputStreamReader(this.getClass()
  500. .getResourceAsStream("session.dtd"))));
  501. return null;
  502. }
  503. }
  504. }