1 22 23 package org.gjt.sp.jedit.io; 24 25 import java.awt.Color ; 27 import java.awt.Component ; 28 import java.io.*; 29 import java.util.*; 30 31 import java.util.regex.Pattern ; 32 import java.util.regex.PatternSyntaxException ; 33 34 import org.gjt.sp.jedit.msg.PropertiesChanged; 35 import org.gjt.sp.jedit.*; 36 import org.gjt.sp.jedit.bufferio.BufferLoadRequest; 37 import org.gjt.sp.jedit.bufferio.BufferSaveRequest; 38 import org.gjt.sp.jedit.bufferio.BufferInsertRequest; 39 import org.gjt.sp.jedit.bufferio.BufferIORequest; 40 import org.gjt.sp.util.Log; 41 import org.gjt.sp.util.ProgressObserver; 42 import org.gjt.sp.util.IOUtilities; 43 import org.gjt.sp.util.StandardUtilities; 44 46 105 public abstract class VFS 106 { 107 109 113 public static final int READ_CAP = 1 << 0; 114 115 119 public static final int WRITE_CAP = 1 << 1; 120 121 132 public static final int BROWSE_CAP = 1 << 2; 133 134 138 public static final int DELETE_CAP = 1 << 3; 139 140 144 public static final int RENAME_CAP = 1 << 4; 145 146 150 public static final int MKDIR_CAP = 1 << 5; 151 152 157 public static final int LOW_LATENCY_CAP = 1 << 6; 158 159 163 public static final int CASE_INSENSITIVE_CAP = 1 << 7; 164 165 167 172 public static final String EA_TYPE = "type"; 173 174 178 public static final String EA_STATUS = "status"; 179 180 184 public static final String EA_SIZE = "size"; 185 186 190 public static final String EA_MODIFIED = "modified"; 191 193 public static int IOBUFSIZE = 32678; 194 195 200 public VFS(String name) 201 { 202 this(name,0); 203 } 205 211 public VFS(String name, int caps) 212 { 213 this.name = name; 214 this.caps = caps; 215 this.extAttrs = new String [] { EA_SIZE, EA_TYPE }; 217 } 219 227 public VFS(String name, int caps, String [] extAttrs) 228 { 229 this.name = name; 230 this.caps = caps; 231 this.extAttrs = extAttrs; 232 } 234 240 public String getName() 241 { 242 return name; 243 } 245 250 public int getCapabilities() 251 { 252 return caps; 253 } 255 260 public String [] getExtendedAttributes() 261 { 262 return extAttrs; 263 } 265 274 public String showBrowseDialog(Object [] session, Component comp) 275 { 276 return null; 277 } 279 285 public String getFileName(String path) 286 { 287 if(path.equals("/")) 288 return path; 289 290 while(path.endsWith("/") || path.endsWith(File.separator)) 291 path = path.substring(0,path.length() - 1); 292 293 int index = Math.max(path.lastIndexOf('/'), 294 path.lastIndexOf(File.separatorChar)); 295 if(index == -1) 296 index = path.indexOf(':'); 297 298 if(index == -1 || index == path.length() - 1) 300 return path; 301 302 return path.substring(index + 1); 303 } 305 313 public String getParentOfPath(String path) 314 { 315 int lastIndex = path.length() - 1; 318 while(lastIndex > 0 319 && (path.charAt(lastIndex) == File.separatorChar 320 || path.charAt(lastIndex) == '/')) 321 { 322 lastIndex--; 323 } 324 325 int count = Math.max(0,lastIndex); 326 int index = path.lastIndexOf(File.separatorChar,count); 327 if(index == -1) 328 index = path.lastIndexOf('/',count); 329 if(index == -1) 330 { 331 index = path.lastIndexOf(':'); 334 } 335 336 return path.substring(0,index + 1); 337 } 339 355 public String constructPath(String parent, String path) 356 { 357 return parent + path; 358 } 360 365 public char getFileSeparator() 366 { 367 return '/'; 368 } 370 385 public String getTwoStageSaveName(String path) 386 { 387 return MiscUtilities.constructPath(getParentOfPath(path), 388 '#' + getFileName(path) + "#save#"); 389 } 391 397 public void reloadDirectory(String path) {} 399 409 public Object createVFSSession(String path, Component comp) 410 { 411 return new Object (); 412 } 414 422 public boolean load(View view, Buffer buffer, String path) 423 { 424 if((getCapabilities() & READ_CAP) == 0) 425 { 426 VFSManager.error(view,path,"vfs.not-supported.load",new String [] { name }); 427 return false; 428 } 429 430 Object session = createVFSSession(path,view); 431 if(session == null) 432 return false; 433 434 if((getCapabilities() & WRITE_CAP) == 0) 435 buffer.setReadOnly(true); 436 437 BufferIORequest request = new BufferLoadRequest( 438 view,buffer,session,this,path); 439 if(buffer.isTemporary()) 440 request.run(); 442 else 443 VFSManager.runInWorkThread(request); 444 445 return true; 446 } 448 456 public boolean save(View view, Buffer buffer, String path) 457 { 458 if((getCapabilities() & WRITE_CAP) == 0) 459 { 460 VFSManager.error(view,path,"vfs.not-supported.save",new String [] { name }); 461 return false; 462 } 463 464 Object session = createVFSSession(path,view); 465 if(session == null) 466 return false; 467 468 473 if(!path.equals(buffer.getPath())) 474 buffer.unsetProperty(Buffer.BACKED_UP); 475 476 VFSManager.runInWorkThread(new BufferSaveRequest( 477 view,buffer,session,this,path)); 478 return true; 479 } 481 498 public static boolean copy(ProgressObserver progress, VFS sourceVFS, Object sourceSession,String sourcePath, 499 VFS targetVFS, Object targetSession,String targetPath, Component comp, boolean canStop) 500 throws IOException 501 { 502 if (progress != null) 503 progress.setStatus("Initializing"); 504 505 InputStream in = null; 506 OutputStream out = null; 507 try 508 { 509 if (progress != null) 510 { 511 VFSFile sourceVFSFile = sourceVFS._getFile(sourceSession, sourcePath, comp); 512 if (sourceVFSFile == null) 513 throw new FileNotFoundException(sourcePath); 514 515 progress.setMaximum(sourceVFSFile.getLength()); 516 } 517 in = new BufferedInputStream(sourceVFS._createInputStream(sourceSession, sourcePath, false, comp)); 518 out = new BufferedOutputStream(targetVFS._createOutputStream(targetSession, targetPath, comp)); 519 boolean copyResult = IOUtilities.copyStream(IOBUFSIZE, progress, in, out, canStop); 520 VFSManager.sendVFSUpdate(targetVFS, targetPath, true); 521 return copyResult; 522 } 523 finally 524 { 525 IOUtilities.closeQuietly(in); 526 IOUtilities.closeQuietly(out); 527 } 528 } 530 544 public static boolean copy(ProgressObserver progress, String sourcePath,String targetPath, Component comp, boolean canStop) 545 throws IOException 546 { 547 VFS sourceVFS = VFSManager.getVFSForPath(sourcePath); 548 Object sourceSession = sourceVFS.createVFSSession(sourcePath, comp); 549 if (sourceSession == null) 550 { 551 Log.log(Log.WARNING, VFS.class, "Unable to get a valid session from " + sourceVFS + " for path " + sourcePath); 552 return false; 553 } 554 VFS targetVFS = VFSManager.getVFSForPath(targetPath); 555 Object targetSession = targetVFS.createVFSSession(targetPath, comp); 556 if (targetSession == null) 557 { 558 Log.log(Log.WARNING, VFS.class, "Unable to get a valid session from " + targetVFS + " for path " + targetPath); 559 return false; 560 } 561 return copy(progress, sourceVFS, sourceSession, sourcePath, targetVFS, targetSession, targetPath, comp,canStop); 562 } 564 572 public boolean insert(View view, Buffer buffer, String path) 573 { 574 if((getCapabilities() & READ_CAP) == 0) 575 { 576 VFSManager.error(view,path,"vfs.not-supported.load",new String [] { name }); 577 return false; 578 } 579 580 Object session = createVFSSession(path,view); 581 if(session == null) 582 return false; 583 584 VFSManager.runInWorkThread(new BufferInsertRequest( 585 view,buffer,session,this,path)); 586 return true; 587 } 589 591 601 public String _canonPath(Object session, String path, Component comp) 602 throws IOException 603 { 604 return path; 605 } 607 622 public String [] _listDirectory(Object session, String directory, 623 String glob, boolean recursive, Component comp ) 624 throws IOException 625 { 626 String [] retval = null; 627 retval = _listDirectory(session, directory, glob, recursive, comp, true, false); 628 return retval; 629 } 630 631 632 654 public String [] _listDirectory(Object session, String directory, 655 String glob, boolean recursive, Component comp, 656 boolean skipBinary, boolean skipHidden) 657 throws IOException 658 { 659 VFSFileFilter filter = new GlobVFSFileFilter(glob); 660 return _listDirectory(session, directory, filter, 661 recursive, comp, skipBinary, 662 skipHidden); 663 } 665 687 public String [] _listDirectory(Object session, String directory, 688 VFSFileFilter filter, boolean recursive, Component comp, 689 boolean skipBinary, boolean skipHidden) 690 throws IOException 691 { 692 Log.log(Log.DEBUG,this,"Listing " + directory); 693 List files = new ArrayList(100); 694 695 listFiles(session,new ArrayList(),files,directory,filter, 696 recursive, comp, skipBinary, skipHidden); 697 698 String [] retVal = (String [])files.toArray(new String [files.size()]); 699 700 Arrays.sort(retVal,new MiscUtilities.StringICaseCompare()); 701 702 return retVal; 703 } 705 717 public VFSFile[] _listFiles(Object session, String directory, 718 Component comp) 719 throws IOException 720 { 721 return _listDirectory(session,directory,comp); 722 } 724 728 public DirectoryEntry[] _listDirectory(Object session, String directory, 729 Component comp) 730 throws IOException 731 { 732 VFSManager.error(comp,directory,"vfs.not-supported.list",new String [] { name }); 733 return null; 734 } 736 746 public VFSFile _getFile(Object session, String path, 747 Component comp) 748 throws IOException 749 { 750 return _getDirectoryEntry(session,path,comp); 751 } 753 764 public DirectoryEntry _getDirectoryEntry(Object session, String path, 765 Component comp) 766 throws IOException 767 { 768 return null; 769 } 771 775 public static class DirectoryEntry extends VFSFile 776 { 777 781 public DirectoryEntry() 782 { 783 } 785 public DirectoryEntry(String name, String path, String deletePath, 787 int type, long length, boolean hidden) 788 { 789 this.name = name; 790 this.path = path; 791 this.deletePath = deletePath; 792 this.symlinkPath = path; 793 this.type = type; 794 this.length = length; 795 this.hidden = hidden; 796 if(path != null) 797 { 798 VFS vfs = VFSManager.getVFSForPath(path); 800 canRead = ((vfs.getCapabilities() & READ_CAP) != 0); 801 canWrite = ((vfs.getCapabilities() & WRITE_CAP) != 0); 802 } 803 } } 806 815 public boolean _delete(Object session, String path, Component comp) 816 throws IOException 817 { 818 return false; 819 } 821 833 public boolean _rename(Object session, String from, String to, 834 Component comp) throws IOException 835 { 836 return false; 837 } 839 848 public boolean _mkdir(Object session, String directory, Component comp) 849 throws IOException 850 { 851 return false; 852 } 854 864 public void _backup(Object session, String path, Component comp) 865 throws IOException 866 { 867 } 869 882 public InputStream _createInputStream(Object session, 883 String path, boolean ignoreErrors, Component comp) 884 throws IOException 885 { 886 VFSManager.error(comp,path,"vfs.not-supported.load",new String [] { name }); 887 return null; 888 } 890 900 public OutputStream _createOutputStream(Object session, 901 String path, Component comp) 902 throws IOException 903 { 904 VFSManager.error(comp,path,"vfs.not-supported.save",new String [] { name }); 905 return null; 906 } 908 920 public void _saveComplete(Object session, Buffer buffer, String path, 921 Component comp) throws IOException {} 923 937 public void _finishTwoStageSave(Object session, Buffer buffer, String path, 938 Component comp) throws IOException 939 { 940 } 942 952 public void _endVFSSession(Object session, Component comp) 953 throws IOException 954 { 955 } 957 963 public static Color getDefaultColorFor(String name) 964 { 965 synchronized(lock) 966 { 967 if(colors == null) 968 loadColors(); 969 970 for(int i = 0; i < colors.size(); i++) 971 { 972 ColorEntry entry = (ColorEntry)colors.elementAt(i); 973 if(entry.re.matcher(name).matches()) 974 return entry.color; 975 } 976 977 return null; 978 } 979 } 981 987 public static class DirectoryEntryCompare implements Comparator 988 { 989 private boolean sortIgnoreCase, sortMixFilesAndDirs; 990 991 998 public DirectoryEntryCompare(boolean sortMixFilesAndDirs, 999 boolean sortIgnoreCase) 1000 { 1001 this.sortMixFilesAndDirs = sortMixFilesAndDirs; 1002 this.sortIgnoreCase = sortIgnoreCase; 1003 } 1004 1005 public int compare(Object obj1, Object obj2) 1006 { 1007 VFSFile file1 = (VFSFile)obj1; 1008 VFSFile file2 = (VFSFile)obj2; 1009 1010 if(!sortMixFilesAndDirs) 1011 { 1012 if(file1.getType() != file2.getType()) 1013 return file2.getType() - file1.getType(); 1014 } 1015 1016 return StandardUtilities.compareStrings(file1.getName(), 1017 file2.getName(),sortIgnoreCase); 1018 } 1019 } 1021 private String name; 1023 private int caps; 1024 private String [] extAttrs; 1025 private static Vector colors; 1026 private static Object lock = new Object (); 1027 1028 static 1030 { 1031 EditBus.addToBus(new EBComponent() 1032 { 1033 public void handleMessage(EBMessage msg) 1034 { 1035 if(msg instanceof PropertiesChanged) 1036 { 1037 synchronized(lock) 1038 { 1039 colors = null; 1040 } 1041 } 1042 } 1043 }); 1044 } 1046 private void listFiles(Object session, List stack, 1048 List files, String directory, VFSFileFilter filter, boolean recursive, 1049 Component comp, boolean skipBinary, boolean skipHidden) throws IOException 1050 { 1051 if(stack.contains(directory)) 1052 { 1053 Log.log(Log.ERROR,this, 1054 "Recursion in _listDirectory(): " 1055 + directory); 1056 return; 1057 } 1058 1059 stack.add(directory); 1060 1061 VFSFile[] _files = _listFiles(session,directory, 1062 comp); 1063 if(_files == null || _files.length == 0) 1064 return; 1065 1066 for(int i = 0; i < _files.length; i++) 1067 { 1068 VFSFile file = _files[i]; 1069 if (skipHidden && (file.isHidden() || MiscUtilities.isBackup(file.getName()))) 1070 continue; 1071 if(!filter.accept(file)) 1072 continue; 1073 if(file.getType() == VFSFile.DIRECTORY 1074 || file.getType() == VFSFile.FILESYSTEM) 1075 { 1076 if(recursive) 1077 { 1078 String canonPath = _canonPath(session, 1080 file.getPath(),comp); 1081 if(!MiscUtilities.isURL(canonPath)) 1082 canonPath = MiscUtilities.resolveSymlinks(canonPath); 1083 1084 listFiles(session,stack,files, 1085 canonPath,filter,recursive, 1086 comp, skipBinary, skipHidden); 1087 } 1088 1089 } 1090 else { 1092 if (skipBinary && file.isBinary(session)) 1093 continue; 1094 1095 Log.log(Log.DEBUG,this,file.getPath()); 1096 files.add(file.getPath()); 1097 } 1098 } 1099 } 1101 private static void loadColors() 1103 { 1104 synchronized(lock) 1105 { 1106 colors = new Vector(); 1107 1108 if(!jEdit.getBooleanProperty("vfs.browser.colorize")) 1109 return; 1110 1111 String glob; 1112 int i = 0; 1113 while((glob = jEdit.getProperty("vfs.browser.colors." + i + ".glob")) != null) 1114 { 1115 try 1116 { 1117 colors.addElement(new ColorEntry( 1118 Pattern.compile(StandardUtilities.globToRE(glob)), 1119 jEdit.getColorProperty( 1120 "vfs.browser.colors." + i + ".color", 1121 Color.black))); 1122 } 1123 catch(PatternSyntaxException e) 1124 { 1125 Log.log(Log.ERROR,VFS.class,"Invalid regular expression: " 1126 + glob); 1127 Log.log(Log.ERROR,VFS.class,e); 1128 } 1129 1130 i++; 1131 } 1132 } 1133 } 1135 static class ColorEntry 1137 { 1138 Pattern re; 1139 Color color; 1140 1141 ColorEntry(Pattern re, Color color) 1142 { 1143 this.re = re; 1144 this.color = color; 1145 } 1146 } 1148 } 1150 | Popular Tags |