source: trunk/src/org/expeditee/gui/FrameIO.java@ 570

Last change on this file since 570 was 570, checked in by jts21, 11 years ago

Add settings package which uses reflection to allow changing settings without hard coding the code to change every setting.

  • Currently only works for String/Int/Boolean/Double values
  • Supports default values by looking for fields with the prefix 'default', and will reset unset values to their default if a default exists.
  • For more complex settings (e.g. proxy settings), there is a "onParsed()" callback which can be used to run additional code, and (in the case of the password widget) parse abnormal items.
  • Some of the settings code in FrameUtils.ParseProfile has already been commented out since it's handled by default with the new Settings package. The rest could be moved over to UserSettings.onParsed(). Given the number of settings that remain to be moved, it may be a good idea to add the possibility for setting-specific onParsed() callbacks (could be done quite easily, similarly to how default values are handled).
File size: 44.1 KB
Line 
1package org.expeditee.gui;
2
3import java.io.BufferedOutputStream;
4import java.io.BufferedReader;
5import java.io.BufferedWriter;
6import java.io.File;
7import java.io.FileInputStream;
8import java.io.FileNotFoundException;
9import java.io.FileOutputStream;
10import java.io.FileReader;
11import java.io.FileWriter;
12import java.io.IOException;
13import java.io.OutputStream;
14import java.io.OutputStreamWriter;
15import java.io.Writer;
16import java.sql.Time;
17import java.util.Collection;
18import java.util.HashMap;
19import java.util.LinkedList;
20
21import org.expeditee.actions.Actions;
22import org.expeditee.agents.ExistingFramesetException;
23import org.expeditee.io.Conversion;
24import org.expeditee.io.ExpReader;
25import org.expeditee.io.ExpWriter;
26import org.expeditee.io.FrameReader;
27import org.expeditee.io.FrameWriter;
28import org.expeditee.io.KMSReader;
29import org.expeditee.io.KMSWriter;
30import org.expeditee.items.Item;
31import org.expeditee.items.ItemUtils;
32import org.expeditee.items.PermissionPair;
33import org.expeditee.items.UserAppliedPermission;
34import org.expeditee.items.Text;
35import org.expeditee.network.FrameShare;
36import org.expeditee.settings.UserSettings;
37import org.expeditee.stats.Formatter;
38import org.expeditee.stats.Logger;
39import org.expeditee.stats.SessionStats;
40
41/**
42 * This class provides static methods for all saving and loading of Frames
43 * to\from disk. This class also handles any caching of previously loaded
44 * Frames.
45 *
46 * @author jdm18
47 *
48 */
49public class FrameIO {
50
51 private static final char FRAME_NAME_LAST_CHAR = 'A';
52
53 public static void changeParentFolder(String newFolder) {
54 PARENT_FOLDER = newFolder;
55 PUBLIC_PATH = PARENT_FOLDER + "public" + File.separator;
56 FRAME_PATH = PARENT_FOLDER + "framesets" + File.separator;
57 MESSAGES_PATH = PARENT_FOLDER + "messages" + File.separator;
58 TRASH_PATH = PARENT_FOLDER + "trash" + File.separator;
59 IMAGES_PATH = PARENT_FOLDER + IMAGES_FOLDER;
60 HELP_PATH = PARENT_FOLDER + "documentation" + File.separator;
61 DICT_PATH = PARENT_FOLDER + "dict" + File.separator;
62 PROFILE_PATH = PARENT_FOLDER + "profiles" + File.separator;
63 EXPORTS_DIR = PARENT_FOLDER + "exports" + File.separator;
64 STATISTICS_DIR = PARENT_FOLDER + "statistics" + File.separator;
65 LOGS_DIR = PARENT_FOLDER + "logs" + File.separator;
66 }
67
68 /**
69 * The default location for storing the framesets. Each frameset has its own
70 * subdirectory in this directory.
71 */
72 public static String IMAGES_FOLDER = "images" + File.separator;
73
74 public static String TRASH_PATH;
75
76 public static String PARENT_FOLDER;
77
78 public static String FRAME_PATH;
79
80 public static String MESSAGES_PATH;
81
82 public static String PUBLIC_PATH;
83
84 public static String IMAGES_PATH;
85
86 public static String HELP_PATH;
87
88 public static String DICT_PATH;
89
90 public static String PROFILE_PATH;
91
92 public static String EXPORTS_DIR;
93
94 public static String STATISTICS_DIR;
95
96 public static String LOGS_DIR;
97
98 private static final String INF_FILENAME = "frame.inf";
99
100 public static final String ILLEGAL_CHARS = ";:\\/?";
101
102 public static final int MAX_NAME_LENGTH = 64;
103
104 public static final int MAX_CACHE = 100;
105
106 private static HashMap<String, Frame> _Cache = new FrameCache();
107
108 // private static HashMap<String, String> _FramesetNameCache = new
109 // HashMap<String, String>();
110
111 private static boolean ENABLE_CACHE = true;
112
113 private static boolean _UseCache = true;
114
115 private static boolean _SuspendedCache = false;
116
117 // All methods are static, this should not be instantiated
118 private FrameIO() {
119 }
120
121 public static boolean isCacheOn() {
122 return _UseCache && ENABLE_CACHE;
123 }
124
125 public static void Precache(String framename) {
126 // if the cache is turned off, do nothing
127 if (!isCacheOn())
128 return;
129
130 // if the frame is already in the cache, do nothing
131 if (_Cache.containsKey(framename.toLowerCase()))
132 return;
133
134 // otherwise, load the frame and put it in the cache
135 Logger.Log(Logger.SYSTEM, Logger.LOAD, "Precaching " + framename + ".");
136
137 // do not display errors encountered to the user
138 // (they will be shown at load time)
139 MessageBay.supressMessages(true);
140 // loading automatically caches the frame is caching is turned on
141 LoadFromDisk(framename, null, false);
142 MessageBay.supressMessages(false);
143 }
144
145 /**
146 * Checks if a string is a representation of a positive integer.
147 *
148 * @param s
149 * @return true if s is a positive integer
150 */
151 public static boolean isPositiveInteger(String s) {
152 if (s == null || s.length() == 0)
153 return false;
154
155 for (int i = 0; i < s.length(); i++) {
156 if (!Character.isDigit(s.charAt(i)))
157 return false;
158 }
159 return true;
160 }
161
162 public static Frame LoadFrame(String frameName) {
163 return LoadFrame(frameName, null, false);
164 }
165
166 public static Frame LoadFrame(String frameName, String path) {
167 return LoadFrame(frameName, path, false);
168 }
169
170 public static Frame LoadFrame(String frameName, String path,
171 boolean ignoreAnnotations) {
172 if (!isValidFrameName(frameName))
173 return null;
174
175 String frameNameLower = frameName.toLowerCase();
176 // first try reading from cache
177 if (isCacheOn() && _Cache.containsKey(frameNameLower)) {
178 Logger.Log(Logger.SYSTEM, Logger.LOAD, "Loading " + frameName
179 + " from cache.");
180 Frame frame = _Cache.get(frameNameLower);
181 return frame;
182 }
183
184 Logger.Log(Logger.SYSTEM, Logger.LOAD, "Loading " + frameName
185 + " from disk.");
186
187 return LoadFromDisk(frameName, path, ignoreAnnotations);
188 }
189
190 public static BufferedReader LoadPublicFrame(String frameName) {
191 String fullPath = FrameIO.getFrameFullPathName(PUBLIC_PATH, frameName);
192
193 if (fullPath == null)
194 return null;
195
196 File frameFile = new File(fullPath);
197 if (frameFile.exists() && frameFile.canRead()) {
198 try {
199 return new BufferedReader(new FileReader(frameFile));
200 } catch (FileNotFoundException e) {
201 e.printStackTrace();
202 }
203 }
204 return null;
205 }
206
207 private static Frame LoadFromDisk(String framename, String knownPath,
208 boolean ignoreAnnotations) {
209 Frame loaded = null;
210
211 if (knownPath != null) {
212 loaded = LoadKnowPath(knownPath, framename);
213 } else {
214
215 for (String path : UserSettings.FrameDirs) {
216 loaded = LoadKnowPath(path, framename);
217 if (loaded != null) {
218 break;
219 }
220 }
221 }
222
223 if (loaded == null && FrameShare.getInstance() != null) {
224 loaded = FrameShare.getInstance().loadFrame(framename, knownPath);
225 }
226
227 if (loaded != null) {
228 FrameUtils.Parse(loaded, true, ignoreAnnotations);
229 }
230
231 return loaded;
232 }
233
234 /**
235 * Gets a list of all the framesets available to the user
236 *
237 * @return a string containing a list of all the available framesets on
238 * separate lines
239 */
240 public static String getFramesetList() {
241 StringBuffer list = new StringBuffer();
242
243 for (String path : UserSettings.FrameDirs) {
244 File files = new File(path);
245 if (!files.exists())
246 continue;
247 for (File f : (new File(path)).listFiles()) {
248 if (f.isDirectory()) {
249 list.append(f.getName()).append('\n');
250 }
251 }
252 }
253 // remove the final new line char
254 list.deleteCharAt(list.length() - 1);
255 return list.toString();
256 }
257
258 /**
259 * Gets the full path and file name of the frame.
260 *
261 * @param path-
262 * the directory in which to look for the frameset containing the
263 * frame.
264 * @param frameName-
265 * the name of the frame for which the path is being requested.
266 * @return null if the frame can not be located.
267 */
268 public static synchronized String getFrameFullPathName(String path,
269 String frameName) {
270 String source = path + Conversion.getFramesetName(frameName)
271 + File.separator;
272
273 File tester = new File(source);
274 if (!tester.exists())
275 return null;
276
277 // check for the new file name format
278 String fullPath = source + Conversion.getFrameNumber(frameName)
279 + ExpReader.EXTENTION;
280 tester = new File(fullPath);
281
282 if (tester.exists())
283 return fullPath;
284
285 // check for oldfile name format
286 fullPath = source + Conversion.getFramesetName(frameName) + "."
287 + Conversion.getFrameNumber(frameName);
288 tester = new File(fullPath);
289
290 if (tester.exists())
291 return fullPath;
292
293 return null;
294 }
295
296 public static boolean canAccessFrame(String frameName) {
297 Frame current = DisplayIO.getCurrentFrame();
298 // Just in case the current frame is not yet saved...
299 if (frameName.equals(current.getName())) {
300 FrameIO.SaveFrame(current, false, false);
301 current.change();
302 return true;
303 }
304
305 for (String path : UserSettings.FrameDirs) {
306 if (getFrameFullPathName(path, frameName) != null)
307 return true;
308 }
309 return false;
310 }
311
312 public static Collection<String> searchFrame(String frameName,
313 String pattern, String path) {
314 String fullPath = null;
315 if (path == null) {
316 for (String possiblePath : UserSettings.FrameDirs) {
317 fullPath = getFrameFullPathName(possiblePath, frameName);
318 if (fullPath != null)
319 break;
320 }
321 } else {
322 fullPath = getFrameFullPathName(path, frameName);
323 }
324 // If the frame was not located return null
325 if (fullPath == null)
326 return null;
327 Collection<String> results = new LinkedList<String>();
328 // Open the file and search the text items
329 try {
330 BufferedReader reader = new BufferedReader(new FileReader(fullPath));
331 String next;
332 while (reader.ready() && ((next = reader.readLine()) != null)) {
333 if (next.startsWith("T")) {
334 String toSearch = next.substring(2);
335 if (toSearch.toLowerCase().contains(pattern))
336 results.add(toSearch);
337 }
338 }
339 } catch (FileNotFoundException e) {
340 e.printStackTrace();
341 return null;
342 } catch (IOException e) {
343 e.printStackTrace();
344 }
345 return results;
346 }
347
348 private static Frame LoadKnowPath(String path, String frameName) {
349 String fullPath = getFrameFullPathName(path, frameName);
350 if (fullPath == null)
351 return null;
352
353 try {
354 FrameReader reader;
355
356 if (fullPath.endsWith(ExpReader.EXTENTION)) {
357 reader = new ExpReader(frameName);
358 } else {
359 reader = new KMSReader();
360 }
361 Frame frame = reader.readFrame(fullPath);
362
363 if (frame == null) {
364 MessageBay.errorMessage("Error: " + frameName
365 + " could not be successfully loaded.");
366 return null;
367 }
368
369 frame.setPath(path);
370
371 // do not put 0 frames or virtual frames into the cache
372 // Why are zero frames not put in the cache
373 if (_Cache.size() > MAX_CACHE)
374 _Cache.clear();
375
376 if (frame.getNumber() > 0 && isCacheOn())
377 _Cache.put(frameName.toLowerCase(), frame);
378
379 return frame;
380 } catch (IOException ioe) {
381 ioe.printStackTrace();
382 Logger.Log(ioe);
383 } catch (Exception e) {
384 e.printStackTrace();
385 Logger.Log(e);
386 MessageBay.errorMessage("Error: " + frameName
387 + " could not be successfully loaded.");
388 }
389
390 return null;
391 }
392
393 public static void Reload() {
394 // disable cache
395 boolean cache = _UseCache;
396
397 _UseCache = false;
398 Frame fresh = FrameIO.LoadFrame(DisplayIO.getCurrentFrame().getName());
399 _UseCache = cache;
400 if (_Cache.containsKey(fresh.getName().toLowerCase()))
401 addToCache(fresh);
402 DisplayIO.setCurrentFrame(fresh, false);
403 }
404
405 public static Frame LoadPrevious(Frame current) {
406 checkTDFC(current);
407
408 // the current name and number
409 String name = current.getFramesetName();
410 int num = current.getNumber() - 1;
411
412 // loop until a frame that exists is found
413 for (; num >= 0; num--) {
414 Frame f = LoadFrame(name + num, current.getPath());
415 if (f != null)
416 return f;
417 }
418
419 // if we did not find another Frame then this one must be the last one
420 // in the frameset
421 MessageBay
422 .displayMessageOnce("This is the first frame in the frameset");
423 return null;
424 }
425
426 /**
427 * Returns the next Frame in the current Frameset (The Frame with the next
428 * highest Frame number) If the current Frame is the last one in the
429 * Frameset, or an error occurs then null is returned.
430 *
431 * @return The Frame after this one in the current frameset, or null
432 */
433 public static Frame LoadNext(Frame current) {
434 checkTDFC(current);
435
436 // the current name and number
437 int num = current.getNumber() + 1;
438 int max = num + 1;
439 String name = current.getFramesetName();
440
441 // read the maximum from the INF file
442 try {
443 max = ReadINF(current.getPath(), current.getFramesetName(), false);
444 } catch (IOException ioe) {
445 MessageBay.errorMessage("Error loading INF file for frameset '"
446 + name + "'");
447 return null;
448 }
449
450 // loop until a frame that exists is found
451 for (; num <= max; num++) {
452 Frame f = LoadFrame(name + num, current.getPath());
453 if (f != null)
454 return f;
455 }
456
457 // if we did not find another Frame then this one must be the last one
458 // in the frameset
459 MessageBay.displayMessageOnce("This is the last frame in the frameset");
460 return null;
461 }
462
463 /**
464 * This method checks if the current frame has just been created with TDFC.
465 * If it has the frame is saved regardless of whether it has been edited or
466 * not and the TDFC item property is cleared. This is to ensure that the
467 * link is saved on the parent frame.
468 *
469 * @param current
470 */
471 public static void checkTDFC(Frame current) {
472 if (FrameUtils.getTdfcItem() != null) {
473 FrameUtils.setTdfcItem(null);
474 current.change();
475 }
476 }
477
478 public static Frame LoadLast(String framesetName, String path) {
479 // read the maximum from the INF file
480 int max;
481 try {
482 max = ReadINF(path, framesetName, false);
483 } catch (IOException ioe) {
484 MessageBay.errorMessage("Error loading INF file for frameset '"
485 + framesetName + "'");
486 return null;
487 }
488
489 // loop backwards until a frame that exists is found
490 for (int num = max; num > 0; num--) {
491 Frame f = LoadFromDisk(framesetName + num, path, false);
492 if (f != null)
493 return f;
494 }
495
496 // if we did not find another Frame then this one must be the last one
497 // in the frameset
498 MessageBay.displayMessage("This is the last frame in the frameset");
499 return null;
500 }
501
502 public static Frame LoadZero(String framesetName, String path) {
503 return LoadFrame(framesetName + 0);
504 }
505
506 public static Frame LoadZero() {
507 Frame current = DisplayIO.getCurrentFrame();
508 return LoadZero(current.getFramesetName(), current.getPath());
509 }
510
511 public static Frame LoadLast() {
512 Frame current = DisplayIO.getCurrentFrame();
513 return LoadLast(current.getFramesetName(), current.getPath());
514 }
515
516 public static Frame LoadNext() {
517 return LoadNext(DisplayIO.getCurrentFrame());
518 }
519
520 public static Frame LoadPrevious() {
521 return LoadPrevious(DisplayIO.getCurrentFrame());
522 }
523
524 /**
525 * Deletes the given Frame on disk and removes the cached Frame if there is
526 * one. Also adds the deleted frame into the deletedFrames frameset.
527 *
528 * @param toDelete
529 * The Frame to be deleted
530 * @return The name the deleted frame was changed to, or null if the delete
531 * failed
532 */
533 public static String DeleteFrame(Frame toDelete) throws IOException,
534 SecurityException {
535 if (toDelete == null)
536 return null;
537
538 // Dont delete the zero frame
539 if (toDelete.getNumber() == 0) {
540 throw new SecurityException("Deleting a zero frame is illegal");
541 }
542
543 // Dont delete the zero frame
544 if (!toDelete.isLocal()) {
545 throw new SecurityException("Attempted to delete remote frame");
546 }
547
548 SaveFrame(toDelete);
549
550 // Copy deleted frames to the DeletedFrames frameset
551 // get the last used frame in the destination frameset
552 final String DELETED_FRAMES = "DeletedFrames";
553 int lastNumber = FrameIO.getLastNumber(DELETED_FRAMES);
554 String framePath;
555 try {
556 // create the new frameset
557 Frame one = FrameIO.CreateFrameset(DELETED_FRAMES, toDelete
558 .getPath());
559 framePath = one.getPath();
560 lastNumber = 0;
561 } catch (Exception e) {
562 Frame zero = FrameIO.LoadFrame(DELETED_FRAMES + "0");
563 framePath = zero.getPath();
564 }
565
566 // get the fill path to determine which file version it is
567 String source = getFrameFullPathName(toDelete.getPath(), toDelete
568 .getName());
569
570 String oldFrameName = toDelete.getName().toLowerCase();
571 // Now save the frame in the new location
572 toDelete.setFrameset(DELETED_FRAMES);
573 toDelete.setFrameNumber(lastNumber + 1);
574 toDelete.setPath(framePath);
575 ForceSaveFrame(toDelete);
576
577 if (_Cache.containsKey(oldFrameName))
578 _Cache.remove(oldFrameName);
579
580 File del = new File(source);
581
582 java.io.FileInputStream ff = new java.io.FileInputStream(del);
583 ff.close();
584
585 if (del.delete()) {
586 return toDelete.getName();
587 }
588
589 return null;
590 }
591
592 /**
593 * Creates a new Frame in the given frameset and assigns it the given Title,
594 * which can be null. The newly created Frame is a copy of the frameset's .0
595 * file with the number updated based on the last recorded Frame name in the
596 * frameset's INF file.
597 *
598 * @param frameset
599 * The frameset to create the new Frame in
600 * @param frameTitle
601 * The title to assign to the newly created Frame (can be NULL).
602 * @return The newly created Frame.
603 */
604 public static synchronized Frame CreateFrame(String frameset,
605 String frameTitle, String templateFrame) throws RuntimeException {
606
607 if (!FrameIO.isValidFramesetName(frameset)) {
608 throw new RuntimeException(frameset
609 + " is not a valid frameset name");
610 }
611
612 int next = -1;
613
614 // disable caching of 0 frames
615 // Mike says: Why is caching of 0 frames being disabled?
616 /*
617 * Especially since 0 frames are not event put into the cache in the
618 * frist place
619 */
620 // SuspendCache();
621 /*
622 * Suspending the cache causes infinate loops when trying to load a zero
623 * frame which has a ao which contains an v or av which contains a link
624 * to the ao frame
625 */
626
627 String zeroFrameName = frameset + "0";
628 Frame destFramesetZero = LoadFrame(zeroFrameName);
629 if (destFramesetZero == null) {
630 throw new RuntimeException(zeroFrameName + " could not be found");
631 }
632
633 Frame template = null;
634 if (templateFrame == null) {
635 // load in frame.0
636 template = destFramesetZero;
637 } else {
638 template = LoadFrame(templateFrame);
639 if (template == null) {
640 throw new RuntimeException("LinkTemplate " + templateFrame
641 + " could not be found");
642 }
643 }
644
645 ResumeCache();
646
647 // read the next number from the INF file
648 try {
649 next = ReadINF(destFramesetZero.getPath(), frameset, true);
650 } catch (IOException ioe) {
651 ioe.printStackTrace();
652 throw new RuntimeException("INF file could not be read");
653 }
654
655 // Remove the old frame from the cashe then add the new one
656 // TODO figure out some way that we can put both in the cache
657 _Cache.remove(template.getName().toLowerCase());
658 // set the number and title of the new frame
659 template.setName(frameset, ++next);
660 template.setTitle(frameTitle);
661 // _Cache.put(template.getName().toLowerCase(), template);
662
663 Logger.Log(Logger.SYSTEM, Logger.TDFC, "Creating new frame: "
664 + template.getName() + " from TDFC");
665
666 template.setOwner(UserSettings.UserName);
667 template.reset();
668 template.resetDateCreated();
669
670 for (Item i : template.getItems()) {
671 if (ItemUtils.startsWithTag(i, ItemUtils.TAG_PARENT))
672 i.setLink(null);
673 }
674
675 // do auto shrinking of the title IF not in twin frames mode
676 Item titleItem = template.getTitleItem();
677
678 if (!DisplayIO.isTwinFramesOn()) {
679 if ((titleItem.getX() + 1) < template.getNameItem().getX()) {
680 while (titleItem.getSize() > Text.MINIMUM_FONT_SIZE
681 && titleItem.getBoundsWidth() + titleItem.getX() > template
682 .getNameItem().getX()) {
683 titleItem.setSize(titleItem.getSize() - 1);
684
685 }
686 } else {
687 System.out.println("Bad title x position: " + titleItem.getX());
688 }
689 }
690
691 // Assign a width to the title.
692 titleItem.setRightMargin(template.getNameItem().getX(), true);
693
694 return template;
695 }
696
697 public static void DisableCache() {
698 _UseCache = false;
699 }
700
701 public static void EnableCache() {
702 _UseCache = true;
703 }
704
705 public static void SuspendCache() {
706 if (_UseCache) {
707 DisableCache();
708 _SuspendedCache = true;
709 } else {
710 _SuspendedCache = false;
711 }
712 }
713
714 public static void ResumeCache() {
715 if (_SuspendedCache) {
716 EnableCache();
717 _SuspendedCache = false;
718 }
719 }
720
721 public static void RefreshCasheImages() {
722 SuspendCache();
723 for (Frame f : _Cache.values())
724 f.setBuffer(null);
725 ResumeCache();
726 }
727
728 /**
729 * Creates a new frameset using the given name. This includes creating a new
730 * subdirectory in the <code>FRAME_PATH</code> directory, Copying over the
731 * default.0 frame from the default frameset, copying the .0 Frame to make a
732 * .1 Frame, and creating the frameset's INF file.
733 *
734 * @param frameset
735 * The name of the Frameset to create
736 * @return The first Frame of the new Frameset (Frame.1)
737 */
738 public static Frame CreateFrameset(String frameset, String path)
739 throws Exception {
740 return CreateFrameset(frameset, path, false);
741 }
742
743 /**
744 * Tests if the given String is a 'proper' framename, that is, the String
745 * must begin with a character, end with a number with 0 or more letters and
746 * numbers in between.
747 *
748 * @param frameName
749 * The String to test for validity as a frame name
750 * @return True if the given framename is proper, false otherwise.
751 */
752 public static boolean isValidFrameName(String frameName) {
753
754 if (frameName == null || frameName.length() < 2)
755 return false;
756
757 int lastCharIndex = frameName.length() - 1;
758 // String must begin with a letter and end with a digit
759 if (!Character.isLetter(frameName.charAt(0))
760 || !Character.isDigit(frameName.charAt(lastCharIndex)))
761 return false;
762
763 // All the characters between first and last must be letters
764 // or digits
765 for (int i = 1; i < lastCharIndex; i++) {
766 if (!isValidFrameNameChar(frameName.charAt(i)))
767 return false;
768 }
769 return true;
770 }
771
772 private static boolean isValidFrameNameChar(char c) {
773 return Character.isLetterOrDigit(c) || c == '-';
774 }
775
776 /**
777 * Saves the given Frame to disk in the corresponding frameset directory.
778 * This is the same as calling SaveFrame(toSave, true)
779 *
780 * @param toSave
781 * The Frame to save to disk
782 */
783 public static String SaveFrame(Frame toSave) {
784 return SaveFrame(toSave, true);
785 }
786
787 /**
788 * Saves a frame.
789 *
790 * @param toSave
791 * the frame to save
792 * @param inc
793 * true if the frames counter should be incremented
794 * @return the text content of the frame
795 */
796 public static String SaveFrame(Frame toSave, boolean inc) {
797 return SaveFrame(toSave, inc, true);
798 }
799
800 /**
801 * Saves the given Frame to disk in the corresponding frameset directory, if
802 * inc is true then the saved frames counter is incremented, otherwise it is
803 * untouched.
804 *
805 * @param toSave
806 * The Frame to save to disk
807 * @param inc
808 * True if the saved frames counter should be incremented, false
809 * otherwise.
810 * @param checkBackup
811 * True if the frame should be checked for the back up tag
812 */
813 public static String SaveFrame(Frame toSave, boolean inc,
814 boolean checkBackup) {
815
816 // TODO When loading a frame maybe append onto the event history too-
817 // with a
818 // break to indicate the end of a session
819
820 if (toSave == null || !toSave.hasChanged() || toSave.isSaved()) {
821 return "";
822 }
823
824 // Dont save if the frame is protected and it exists
825 if (checkBackup && toSave.isReadOnly()) {
826 _Cache.remove(toSave.getName().toLowerCase());
827 return "";
828 }
829
830 /* Dont save the frame if it has the noSave tag */
831 if (toSave.hasAnnotation("nosave")) {
832 Actions.PerformActionCatchErrors(toSave, null, "Restore");
833 return "";
834 }
835
836 // Save frame that is not local through the Networking classes
837 // TODO
838 if (!toSave.isLocal()) {
839 return FrameShare.getInstance().saveFrame(toSave);
840 }
841
842 /* Format the frame if it has the autoFormat tag */
843 if (toSave.hasAnnotation("autoformat")) {
844 Actions.PerformActionCatchErrors(toSave, null, "Format");
845 }
846
847 /**
848 * Get the full path only to determine which format to use for saving
849 * the frame. At this stage use Exp format for saving Exp frames only.
850 * Later this will be changed so that KMS frames will be updated to the
851 * Exp format.
852 */
853 String fullPath = getFrameFullPathName(toSave.getPath(), toSave
854 .getName());
855
856 // Check if the frame exists
857 if (checkBackup && fullPath == null) {
858 // The first time a frame with the backup tag is saved, dont back it
859 // up
860 checkBackup = false;
861 }
862
863 FrameWriter writer = null;
864 int savedVersion;
865 try {
866 // if its a new frame or an existing Exp frame...
867 if (fullPath == null || fullPath.endsWith(ExpReader.EXTENTION)) {
868 writer = new ExpWriter();
869 savedVersion = ExpReader.getVersion(fullPath);
870 } else {
871 writer = new KMSWriter();
872 savedVersion = KMSReader.getVersion(fullPath);
873 }
874
875 // Check if the frame doesnt exist
876 // if (savedVersion < 0) {
877 // /*
878 // * This will happen if the user has two Expeditee's running at
879 // * once and closes the first. When the second one closes the
880 // * messages directory will have been deleted.
881 // */
882 // MessageBay
883 // .errorMessage("Could not save frame that does not exist: "
884 // + toSave.getName());
885 // return null;
886 // }
887
888 // Check if we are trying to save an out of date version
889 if (savedVersion > toSave.getVersion()
890 && !toSave.getFramesetName().equalsIgnoreCase(
891 MessageBay.MESSAGES_FRAMESET_NAME)) {
892 // remove this frame from the cache if it is there
893 // This will make sure links to the original are set correctly
894 _Cache.remove(toSave.getName().toLowerCase());
895 int nextnum = ReadINF(toSave.getPath(), toSave
896 .getFramesetName(), false) + 1;
897 SuspendCache();
898 Frame original = LoadFrame(toSave.getName());
899 toSave.setFrameNumber(nextnum);
900 ResumeCache();
901 // Put the modified version in the cache
902 addToCache(toSave);
903 // Show the messages alerting the user
904 Text originalMessage = new Text(-1);
905 originalMessage.setColor(MessageBay.ERROR_COLOR);
906 originalMessage.setText(original.getName()
907 + " was updated by another user.");
908 originalMessage.setLink(original.getName());
909 Text yourMessage = new Text(-1);
910 yourMessage.setColor(MessageBay.ERROR_COLOR);
911 yourMessage.setText("Your version was renamed "
912 + toSave.getName());
913 yourMessage.setLink(toSave.getName());
914 MessageBay.displayMessage(originalMessage);
915 MessageBay.displayMessage(yourMessage);
916 } else if (checkBackup
917 && ItemUtils.ContainsExactTag(toSave.getItems(),
918 ItemUtils.TAG_BACKUP)) {
919 SuspendCache();
920 String oldFramesetName = toSave.getFramesetName() + "-old";
921
922 Frame original = LoadFrame(toSave.getName());
923 if (original == null)
924 original = toSave;
925 int orignum = original.getNumber();
926
927 int nextnum = -1;
928 try {
929 nextnum = ReadINF(toSave.getPath(), oldFramesetName, false) + 1;
930 } catch (RuntimeException e) {
931 try {
932 CreateFrameset(oldFramesetName, toSave.getPath());
933 nextnum = 1;
934 } catch (Exception e1) {
935 e1.printStackTrace();
936 }
937 // e.printStackTrace();
938 }
939
940 if (nextnum > 0) {
941 original.setFrameset(oldFramesetName);
942 original.setFrameNumber(nextnum);
943 original.setPermission(new PermissionPair(UserAppliedPermission.copy));
944 original.change();
945 SaveFrame(original, false, false);
946 }
947
948 Item i = ItemUtils.FindExactTag(toSave.getItems(),
949 ItemUtils.TAG_BACKUP);
950 i.setLink(original.getName());
951 toSave.setFrameNumber(orignum);
952 ResumeCache();
953 }
954 // Update general stuff about frame
955 setSavedProperties(toSave);
956
957 // int oldMode = FrameGraphics.getMode();
958 // if (oldMode != FrameGraphics.MODE_XRAY)
959 // FrameGraphics.setMode(FrameGraphics.MODE_XRAY, true);
960 writer.writeFrame(toSave);
961 // FrameGraphics.setMode(oldMode, true);
962 toSave.setSaved();
963 if (inc) {
964 SessionStats.SavedFrame(toSave.getName());
965 }
966
967 // avoid out-of-sync frames (when in TwinFrames mode)
968 if (_Cache.containsKey(toSave.getName().toLowerCase()))
969 addToCache(toSave);
970
971 Logger.Log(Logger.SYSTEM, Logger.SAVE, "Saving " + toSave.getName()
972 + " to disk.");
973
974 // check that the INF file is not out of date
975 int last = ReadINF(toSave.getPath(), toSave.getFramesetName(),
976 false);
977 if (last <= toSave.getNumber())
978 WriteINF(toSave.getPath(), toSave.getFramesetName(), toSave
979 .getName());
980
981 // check if this was the profile frame (and thus needs
982 // re-parsing)
983 if (isProfileFrame(toSave)) {
984 Frame profile = FrameIO.LoadFrame(toSave.getFramesetName()
985 + "1");
986 assert (profile != null);
987 FrameUtils.ParseProfile(profile);
988 }
989 } catch (IOException ioe) {
990 ioe.printStackTrace();
991 ioe.getStackTrace();
992 Logger.Log(ioe);
993 return null;
994 }
995
996 return writer.getFileContents();
997 }
998
999 /**
1000 * @param toAdd
1001 */
1002 public static void addToCache(Frame toAdd) {
1003 _Cache.put(toAdd.getName().toLowerCase(), toAdd);
1004 }
1005
1006 /**
1007 * Checks if a frame is in the current user profile frameset.
1008 *
1009 * @param toCheck
1010 * the frame to check
1011 * @return true if the frame is in the current user profile frameset
1012 */
1013 public static boolean isProfileFrame(Frame toCheck) {
1014 if (toCheck.getNumber() == 0)
1015 return false;
1016 return toCheck.getPath().equals(PROFILE_PATH);
1017 // return toCheck.getFramesetName()
1018 // .equalsIgnoreCase(UserSettings.ProfileName);
1019 }
1020
1021 public static Frame LoadProfile(String userName) {
1022 return LoadFrame(userName + "1");
1023 }
1024
1025 public static Frame CreateNewProfile(String username) throws Exception {
1026 Frame profile = CreateFrameset(username, PROFILE_PATH, true);
1027 FrameUtils.CreateDefaultProfile(username, profile);
1028 return profile;
1029 }
1030
1031 /**
1032 * Reads the INF file that corresponds to the given Frame name
1033 *
1034 * @param framename
1035 * The Frame to lookup the INF file for
1036 * @throws IOException
1037 * Any exceptions encountered by the BufferedReader used to read
1038 * the INF.
1039 */
1040 public static int ReadINF(String path, String frameset, boolean update)
1041 throws IOException {
1042 assert (!frameset.endsWith("."));
1043 try {
1044 // read INF
1045 BufferedReader reader;
1046 try {
1047 // Check on the local drive
1048 reader = new BufferedReader(new FileReader(path
1049 + frameset.toLowerCase() + File.separator
1050 + INF_FILENAME));
1051 } catch (Exception e) {
1052 reader = new BufferedReader(new FileReader(path
1053 + frameset.toLowerCase() + File.separator
1054 + frameset.toLowerCase() + ".inf"));
1055 }
1056 String inf = reader.readLine();
1057 reader.close();
1058
1059 int next = Conversion.getFrameNumber(inf);
1060 // update INF file
1061 if (update) {
1062 try {
1063 WriteINF(path, frameset, frameset + (next + 1));
1064 } catch (IOException ioe) {
1065 ioe.printStackTrace();
1066 Logger.Log(ioe);
1067 }
1068 }
1069 return next;
1070 } catch (Exception e) {
1071 }
1072
1073 // Check peers
1074 return FrameShare.getInstance().getInfNumber(path, frameset, update);
1075 }
1076
1077 /**
1078 * Writes the given String out to the INF file corresponding to the current
1079 * frameset.
1080 *
1081 * @param toWrite
1082 * The String to write to the file.
1083 * @throws IOException
1084 * Any exception encountered by the BufferedWriter.
1085 */
1086 public static void WriteINF(String path, String frameset, String frameName)
1087 throws IOException {
1088 try {
1089 assert (!frameset.endsWith("."));
1090
1091 path += frameset.toLowerCase() + File.separator + INF_FILENAME;
1092
1093 BufferedWriter writer = new BufferedWriter(new FileWriter(path));
1094 writer.write(frameName);
1095 writer.close();
1096 } catch (Exception e) {
1097
1098 }
1099 }
1100
1101 public static boolean FrameIsCached(String name) {
1102 return _Cache.containsKey(name);
1103 }
1104
1105 /**
1106 * Gets a frame from the cache.
1107 *
1108 * @param name
1109 * The frame to get from the cache
1110 *
1111 * @return The frame from cache. Null if not cached.
1112 */
1113 public static Frame FrameFromCache(String name) {
1114 return _Cache.get(name);
1115 }
1116
1117 public static String ConvertToValidFramesetName(String toValidate) {
1118 assert (toValidate != null && toValidate.length() > 0);
1119
1120 StringBuffer result = new StringBuffer();
1121
1122 if (Character.isDigit(toValidate.charAt(0))) {
1123 result.append(FRAME_NAME_LAST_CHAR);
1124 }
1125
1126 boolean capital = false;
1127 for (int i = 0; i < toValidate.length()
1128 && result.length() < MAX_NAME_LENGTH; i++) {
1129 char cur = toValidate.charAt(i);
1130
1131 // capitalize all characters after spaces
1132 if (Character.isLetterOrDigit(cur)) {
1133 if (capital) {
1134 capital = false;
1135 result.append(Character.toUpperCase(cur));
1136 } else
1137 result.append(cur);
1138 } else {
1139 capital = true;
1140 }
1141 }
1142 assert (result.length() > 0);
1143 int lastCharIndex = result.length() - 1;
1144 if (!Character.isLetter(result.charAt(lastCharIndex))) {
1145 if (lastCharIndex == MAX_NAME_LENGTH - 1)
1146 result.setCharAt(lastCharIndex, FRAME_NAME_LAST_CHAR);
1147 else
1148 result.append(FRAME_NAME_LAST_CHAR);
1149 }
1150
1151 assert (isValidFramesetName(result.toString()));
1152 return result.toString();
1153 }
1154
1155 public static Frame CreateNewFrame(Item linker) throws RuntimeException {
1156 String title = linker.getName();
1157
1158 String templateLink = linker.getAbsoluteLinkTemplate();
1159 String framesetLink = linker.getAbsoluteLinkFrameset();
1160 String frameset = (framesetLink != null ? framesetLink : DisplayIO
1161 .getCurrentFrame().getFramesetName());
1162
1163 Frame newFrame = FrameIO.CreateFrame(frameset, title, templateLink);
1164 return newFrame;
1165 }
1166
1167 /**
1168 * Creates a new Frameset on disk, including a .0, .1, and .inf files. The
1169 * Default.0 frame is copied to make the initial .0 and .1 Frames
1170 *
1171 * @param name
1172 * The Frameset name to use
1173 * @return The name of the first Frame in the newly created Frameset (the .1
1174 * frame)
1175 */
1176 public static Frame CreateNewFrameset(String name) throws Exception {
1177 String path = DisplayIO.getCurrentFrame().getPath();
1178
1179 // if current frameset is profile directory change it to framesets
1180 if (path.equals(FrameIO.PROFILE_PATH)) {
1181 path = FrameIO.FRAME_PATH;
1182 }
1183
1184 Frame newFrame = FrameIO.CreateFrameset(name, path);
1185
1186 if (newFrame == null) {
1187 // Cant create directories if the path is readonly or there is no
1188 // space available
1189 newFrame = FrameIO.CreateFrameset(name, FrameIO.FRAME_PATH);
1190 }
1191
1192 if (newFrame == null) {
1193 // TODO handle running out of disk space here
1194 }
1195
1196 return newFrame;
1197 }
1198
1199 /**
1200 *
1201 * @param frameset
1202 * @return
1203 */
1204 public static int getLastNumber(String frameset) { // Rob thinks it might
1205 // have been
1206 // GetHighestNumExFrame
1207 // TODO minimise the number of frames being read in!!
1208 int num = -1;
1209
1210 Frame zero = LoadFrame(frameset + "0");
1211
1212 // the frameset does not exist (or has no 0 frame)
1213 if (zero == null)
1214 return -1;
1215
1216 try {
1217 num = ReadINF(zero.getPath(), frameset, false);
1218 } catch (IOException e) {
1219 // TODO Auto-generated catch block
1220 // e.printStackTrace();
1221 }
1222
1223 /*
1224 * Michael doesnt think the code below is really needed... it will just
1225 * slow things down when we are reading frames over a network***** for (;
1226 * num >= 0; num--) { System.out.println("This code is loading frames to
1227 * find the highest existing frame..."); if (LoadFrame(frameset + num) !=
1228 * null) break; }
1229 */
1230
1231 return num;
1232 }
1233
1234 /**
1235 * Checks if a given frameset is accessable.
1236 *
1237 * @param framesetName
1238 * @return
1239 */
1240 public static Boolean canAccessFrameset(String framesetName) {
1241 framesetName = framesetName.toLowerCase();
1242 for (String path : UserSettings.FrameDirs) {
1243 if ((new File(path + framesetName)).exists())
1244 return true;
1245 }
1246 return false;
1247 }
1248
1249 public static Frame CreateFrameset(String frameset, String path,
1250 boolean recreate) throws Exception {
1251 String conversion = frameset + " --> ";
1252
1253 if (!isValidFramesetName(frameset)) {
1254 throw new Exception("Invalid frameset name");
1255 }
1256
1257 if (!recreate && FrameIO.canAccessFrameset(frameset)) {
1258 throw new ExistingFramesetException(frameset);
1259 }
1260
1261 conversion += frameset;
1262 Logger.Log(Logger.SYSTEM, Logger.NEW_FRAMESET, "Frameset Name: "
1263 + conversion);
1264 conversion = frameset;
1265
1266 /**
1267 * TODO: Update this to exclude any\all invalid filename characters
1268 */
1269 // ignore annotation character
1270 if (frameset.startsWith("@"))
1271 frameset = frameset.substring(1);
1272
1273 conversion += " --> " + frameset;
1274 Logger.Log(Logger.SYSTEM, Logger.NEW_FRAMESET, "Name: " + conversion);
1275
1276 // create the new Frameset directory
1277 File dir = new File(path + frameset.toLowerCase() + File.separator);
1278
1279 // If the directory doesnt already exist then create it...
1280 if (!dir.exists()) {
1281 // If the directory couldnt be created, then there is something
1282 // wrong... ie. The disk is full.
1283 if (!dir.mkdirs()) {
1284 return null;
1285 }
1286 }
1287
1288 // create the new INF file
1289 try {
1290 WriteINF(path, frameset, frameset + '1');
1291 } catch (IOException ioe) {
1292 ioe.printStackTrace();
1293 Logger.Log(ioe);
1294 }
1295
1296 SuspendCache();
1297 // copy the default .0 and .1 files
1298 Frame base = null;
1299 try {
1300 base = LoadFrame(UserSettings.DefaultFrame);
1301 } catch (Exception e) {
1302 }
1303 // The frame may not be accessed for various reasons... in all these
1304 // cases just create a new one
1305 if (base == null) {
1306 base = new Frame();
1307 }
1308
1309 ResumeCache();
1310
1311 base.reset();
1312 base.resetDateCreated();
1313 base.setFrameset(frameset);
1314 base.setFrameNumber(0);
1315 base.setTitle(base.getFramesetName() + "0");
1316 base.setPath(path);
1317 base.change();
1318 base.setOwner(UserSettings.UserName);
1319 SaveFrame(base, false);
1320
1321 base.reset();
1322 base.resetDateCreated();
1323 base.setFrameNumber(1);
1324 base.setTitle(frameset);
1325 base.change();
1326 base.setOwner(UserSettings.UserName);
1327 SaveFrame(base, true);
1328
1329 Logger.Log(Logger.SYSTEM, Logger.NEW_FRAMESET, "Created new frameset: "
1330 + frameset);
1331
1332 return base;
1333 }
1334
1335 /**
1336 * Tests if a frameset name is valid. That is it must begin and end with a
1337 * letter and contain only letters and digits in between.
1338 *
1339 * @param frameset
1340 * the name to be tested
1341 * @return true if the frameset name is valid
1342 */
1343 public static boolean isValidFramesetName(String frameset) {
1344 if (frameset == null) {
1345 return false;
1346 }
1347
1348 int nameLength = frameset.length();
1349 if (frameset.length() <= 0 || nameLength > MAX_NAME_LENGTH) {
1350 return false;
1351 }
1352
1353 int lastCharIndex = nameLength - 1;
1354
1355 if (!Character.isLetter(frameset.charAt(0))
1356 || !Character.isLetter(frameset.charAt(lastCharIndex)))
1357 return false;
1358
1359 for (int i = 1; i < lastCharIndex; i++) {
1360 if (!isValidFrameNameChar(frameset.charAt(i))) {
1361 return false;
1362 }
1363 }
1364 return true;
1365 }
1366
1367 public static boolean deleteFrameset(String framesetName) {
1368 return moveFrameset(framesetName, FrameIO.TRASH_PATH);
1369 }
1370
1371 public static boolean moveFrameset(String framesetName,
1372 String destinationFolder) {
1373 if (!FrameIO.canAccessFrameset(framesetName))
1374 return false;
1375 // Clear the cache
1376 _Cache.clear();
1377
1378 // Search all the available directories for the directory
1379 for (String path : UserSettings.FrameDirs) {
1380 String source = path + framesetName.toLowerCase() + File.separator;
1381 File framesetDirectory = new File(source);
1382 // Once we have found the directory move it
1383 if (framesetDirectory.exists()) {
1384 String destPath = destinationFolder
1385 + framesetName.toLowerCase();
1386 int copyNumber = 1;
1387 File dest = new File(destPath + File.separator);
1388 // Create the destination folder if it doesnt already exist
1389 if (!dest.getParentFile().exists())
1390 dest.mkdirs();
1391 // If a frameset with the same name is already in the
1392 // destination add
1393 // a number to the end
1394 while (dest.exists()) {
1395 dest = new File(destPath + ++copyNumber + File.separator);
1396 }
1397 if (!framesetDirectory.renameTo(dest)) {
1398 for (File f : framesetDirectory.listFiles()) {
1399 if (!f.delete())
1400 return false;
1401 }
1402 if (!framesetDirectory.delete())
1403 return false;
1404 }
1405 return true;
1406 }
1407 }
1408 return false;
1409 }
1410
1411 public static boolean CopyFrameset(String framesetToCopy,
1412 String copiedFrameset) throws Exception {
1413 if (!FrameIO.canAccessFrameset(framesetToCopy))
1414 return false;
1415 if (FrameIO.canAccessFrameset(copiedFrameset))
1416 return false;
1417 // search through all the directories to find the frameset we are
1418 // copying
1419 for (String path : UserSettings.FrameDirs) {
1420 String source = path + framesetToCopy.toLowerCase()
1421 + File.separator;
1422 File framesetDirectory = new File(source);
1423 if (framesetDirectory.exists()) {
1424 // copy the frameset
1425 File copyFramesetDirectory = new File(path
1426 + copiedFrameset.toLowerCase() + File.separator);
1427 if (!copyFramesetDirectory.mkdirs())
1428 return false;
1429 // copy each of the frames
1430 for (File f : framesetDirectory.listFiles()) {
1431 // Ignore hidden files
1432 if (f.getName().charAt(0) == '.')
1433 continue;
1434 String copyPath = copyFramesetDirectory.getAbsolutePath()
1435 + File.separator + f.getName();
1436 FrameIO.copyFile(f.getAbsolutePath(), copyPath);
1437 }
1438 return true;
1439 }
1440 }
1441 return false;
1442 }
1443
1444 /**
1445 * Copies a file from one location to another.
1446 *
1447 * @param existingFile
1448 * @param newFileName
1449 * @throws Exception
1450 */
1451 public static void copyFile(String existingFile, String newFileName)
1452 throws Exception {
1453 FileInputStream is = new FileInputStream(existingFile);
1454 FileOutputStream os = new FileOutputStream(newFileName, false);
1455 int data;
1456 while ((data = is.read()) != -1) {
1457 os.write(data);
1458 }
1459 os.flush();
1460 os.close();
1461 is.close();
1462 }
1463
1464 /**
1465 * Saves a frame regardless of whether or not the frame is marked as having
1466 * been changed.
1467 *
1468 * @param frame
1469 * the frame to save
1470 * @return the contents of the frame or null if it could not be saved
1471 */
1472 public static String ForceSaveFrame(Frame frame) {
1473 frame.change();
1474 return SaveFrame(frame, false);
1475 }
1476
1477 public static boolean isValidLink(String frameName) {
1478 return frameName == null || isPositiveInteger(frameName)
1479 || isValidFrameName(frameName);
1480 }
1481
1482 public static void SavePublicFrame(String peerName, String frameName,
1483 int version, BufferedReader packetContents) {
1484 // TODO handle versioning - add version to the header
1485 // Remote user uploads version based on an old version
1486
1487 // Remove it from the cache so that next time it is loaded we get the up
1488 // todate version
1489 _Cache.remove(frameName.toLowerCase());
1490
1491 // Save to file
1492 String filename = PUBLIC_PATH + Conversion.getFramesetName(frameName)
1493 + File.separator + Conversion.getFrameNumber(frameName)
1494 + ExpReader.EXTENTION;
1495
1496 File file = new File(filename);
1497 // Ensure the file exists
1498 if (file.exists()) {
1499 // Check the versions
1500 int savedVersion = ExpReader.getVersion(filename);
1501
1502 if (savedVersion > version) {
1503 // remove this frame from the cache if it is there
1504 // This will make sure links to the original are set correctly
1505 // _Cache.remove(frameName.toLowerCase());
1506
1507 int nextNum = 0;
1508 try {
1509 nextNum = ReadINF(PUBLIC_PATH, Conversion
1510 .getFramesetName(frameName), false) + 1;
1511 } catch (IOException e) {
1512 e.printStackTrace();
1513 }
1514
1515 String newName = Conversion.getFramesetName(frameName)
1516 + nextNum;
1517 filename = PUBLIC_PATH + Conversion.getFramesetName(frameName)
1518 + File.separator + nextNum + ExpReader.EXTENTION;
1519
1520 // Show the messages alerting the user
1521 Text originalMessage = new Text(-1);
1522 originalMessage.setColor(MessageBay.ERROR_COLOR);
1523 originalMessage.setText(frameName + " was edited by "
1524 + peerName);
1525 originalMessage.setLink(frameName);
1526 Text yourMessage = new Text(-1);
1527 yourMessage.setColor(MessageBay.ERROR_COLOR);
1528 yourMessage.setText("Their version was renamed " + newName);
1529 yourMessage.setLink(newName);
1530 MessageBay.displayMessage(originalMessage);
1531 MessageBay.displayMessage(yourMessage);
1532
1533 Frame editedFrame = FrameIO.LoadFrame(frameName);
1534
1535 FrameShare.getInstance().sendMessage(
1536 frameName + " was recently edited by "
1537 + editedFrame.getLastModifyUser(), peerName);
1538 FrameShare.getInstance().sendMessage(
1539 "Your version was renamed " + newName, peerName);
1540 }
1541 }
1542
1543 // Save the new version
1544 try {
1545 // FileWriter fw = new FileWriter(file);
1546
1547 // Open an Output Stream Writer to set encoding
1548 OutputStream fout = new FileOutputStream(file);
1549 OutputStream bout = new BufferedOutputStream(fout);
1550 Writer fw = new OutputStreamWriter(bout, "UTF-8");
1551
1552 String nextLine = null;
1553 while ((nextLine = packetContents.readLine()) != null) {
1554 fw.write(nextLine + '\n');
1555 }
1556 fw.flush();
1557 fw.close();
1558 MessageBay.displayMessage("Saved remote frame: " + frameName);
1559 } catch (IOException e) {
1560 MessageBay.errorMessage("Error remote saving " + frameName + ": "
1561 + e.getMessage());
1562 e.printStackTrace();
1563 }
1564 // } else {
1565 //
1566 //
1567 //
1568 // MessageBay
1569 // .errorMessage("Recieved save request for unknown public frame: "
1570 // + frameName);
1571 // }
1572 }
1573
1574 public static void setSavedProperties(Frame toSave) {
1575 toSave.setLastModifyDate(Formatter.getDateTime());
1576 toSave.setLastModifyUser(UserSettings.UserName);
1577 toSave.setVersion(toSave.getVersion() + 1);
1578 Time darkTime = new Time(SessionStats.getFrameDarkTime().getTime()
1579 + toSave.getDarkTime().getTime());
1580 Time activeTime = new Time(SessionStats.getFrameActiveTime().getTime()
1581 + toSave.getActiveTime().getTime());
1582 toSave.setDarkTime(darkTime);
1583 toSave.setActiveTime(activeTime);
1584 }
1585
1586}
Note: See TracBrowser for help on using the repository browser.