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

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

Switch back to EXP format, revert changes to Picture class

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.