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

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

New copy/paste handling, add pdfImporter, add dictionary and documentation to resources, other small changes

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