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

Last change on this file since 436 was 436, checked in by davidb, 12 years ago

Fixed typo in comment.

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