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

Last change on this file since 919 was 919, checked in by jts21, 10 years ago

Added license headers to all files, added full GPL3 license file, moved license header generator script to dev/bin/scripts

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