1. /*
  2. * @(#)FileSystemView.java 1.14 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.filechooser;
  8. import javax.swing.event.*;
  9. import javax.swing.*;
  10. import java.io.File;
  11. import java.io.IOException;
  12. import java.util.Vector;
  13. import java.lang.reflect.*;
  14. /**
  15. * FileSystemView is JFileChooser's gateway to the
  16. * file system. Since the JDK1.1 File api doesn't allow
  17. * access to such information as root partitians, file type
  18. * information, or hidden file bits, this class is designed
  19. * to intuit as much OS specific file system information as
  20. * possible.
  21. *
  22. * FileSystemView will eventually delegate its responsibilities
  23. * to io File classes when JDK1.X provides more direct access to
  24. * file system information.
  25. *
  26. * Java Licenses may want to provide a different implemenation of
  27. * FileSystemView to better handle a given operation system.
  28. *
  29. * PENDING(jeff) - need to provide a specification for
  30. * how Mac/OS2/BeOS/etc file systems can modify FileSystemView
  31. * to handle their particular type of file system.
  32. *
  33. * @version 1.14 11/29/01
  34. * @author Jeff Dinkins
  35. */
  36. public abstract class FileSystemView {
  37. static FileSystemView windowsFileSystemView = null;
  38. static FileSystemView unixFileSystemView = null;
  39. //static FileSystemView macFileSystemView = null;
  40. static FileSystemView genericFileSystemView = null;
  41. public static FileSystemView getFileSystemView() {
  42. if(File.separatorChar == '\\') {
  43. if(windowsFileSystemView == null) {
  44. windowsFileSystemView = new WindowsFileSystemView();
  45. }
  46. return windowsFileSystemView;
  47. }
  48. if(File.separatorChar == '/') {
  49. if(unixFileSystemView == null) {
  50. unixFileSystemView = new UnixFileSystemView();
  51. }
  52. return unixFileSystemView;
  53. }
  54. // if(File.separatorChar == ':') {
  55. // if(macFileSystemView == null) {
  56. // macFileSystemView = new MacFileSystemView();
  57. // }
  58. // return macFileSystemView;
  59. //}
  60. if(genericFileSystemView == null) {
  61. genericFileSystemView = new GenericFileSystemView();
  62. }
  63. return genericFileSystemView;
  64. }
  65. /**
  66. * Determines if the given file is a root partition or drive.
  67. */
  68. public abstract boolean isRoot(File f);
  69. /**
  70. * creates a new folder with a default folder name.
  71. */
  72. public abstract File createNewFolder(File containingDir) throws IOException;
  73. /**
  74. * Returns whether a file is hidden or not.
  75. */
  76. public abstract boolean isHiddenFile(File f);
  77. /**
  78. * Returns all root partitians on this system. For example, on Windows,
  79. * this would be the A: through Z: drives.
  80. */
  81. public abstract File[] getRoots();
  82. // Providing default implemenations for the remaining methods
  83. // because most OS file systems will likely be able to use this
  84. // code. If a given OS can't, override these methods in its
  85. // implementation.
  86. public File getHomeDirectory() {
  87. return createFileObject(System.getProperty("user.home"));
  88. }
  89. /**
  90. * Returns a File object constructed in dir from the given filename.
  91. */
  92. public File createFileObject(File dir, String filename) {
  93. if(dir == null) {
  94. return new File(filename);
  95. } else {
  96. return new File(dir, filename);
  97. }
  98. }
  99. /**
  100. * Returns a File object constructed from the given path string.
  101. */
  102. public File createFileObject(String path) {
  103. return new File(path);
  104. }
  105. /**
  106. * gets the list of shown (i.e. not hidden) files
  107. */
  108. public File[] getFiles(File dir, boolean useFileHiding) {
  109. Vector files = new Vector();
  110. // add all files in dir
  111. File [] names = dir.listFiles();
  112. File f;
  113. int nameCount = names == null ? 0 : names.length;
  114. for (int i = 0; i < nameCount; i++) {
  115. f = names[i];
  116. if (f.isFile() || f.isDirectory()) {
  117. if (!useFileHiding || !isHiddenFile(f)) {
  118. files.addElement(f);
  119. }
  120. }
  121. }
  122. return (File[])files.toArray(new File[files.size()]);
  123. }
  124. /**
  125. * Returns the parent directory of dir.
  126. */
  127. public File getParentDirectory(File dir) {
  128. if(dir != null) {
  129. File f = createFileObject(dir.getAbsolutePath());
  130. String parentFilename = f.getParent();
  131. if(parentFilename != null) {
  132. return new File(parentFilename);
  133. }
  134. }
  135. return null;
  136. }
  137. }
  138. /**
  139. * FileSystemView that handles some specific unix-isms.
  140. */
  141. class UnixFileSystemView extends FileSystemView {
  142. private static final Object[] noArgs = {};
  143. private static final Class[] noArgTypes = {};
  144. private static Method listRootsMethod = null;
  145. private static boolean listRootsMethodChecked = false;
  146. public boolean isRoot(File f) {
  147. String path = f.getAbsolutePath();
  148. if(path.length() == 1 && path.charAt(0) == '/') {
  149. return true;
  150. }
  151. return false;
  152. }
  153. /**
  154. * creates a new folder with a default folder name.
  155. */
  156. public File createNewFolder(File containingDir) throws IOException {
  157. if(containingDir == null) {
  158. throw new IOException("Containing directory is null:");
  159. }
  160. File newFolder = null;
  161. // Unix - using OpenWindow's default folder name. Can't find one for Motif/CDE.
  162. newFolder = createFileObject(containingDir, "NewFolder");
  163. int i = 1;
  164. while (newFolder.exists() && (i < 100)) {
  165. newFolder = createFileObject(containingDir, "NewFolder." + i);
  166. i++;
  167. }
  168. if(newFolder.exists()) {
  169. throw new IOException("Directory already exists:" + newFolder.getAbsolutePath());
  170. } else {
  171. newFolder.mkdirs();
  172. }
  173. return newFolder;
  174. }
  175. /**
  176. * Returns whether a file is hidden or not. On Unix,
  177. * all files that begin with "." are hidden.
  178. */
  179. public boolean isHiddenFile(File f) {
  180. if(f != null) {
  181. String filename = f.getName();
  182. if(filename.charAt(0) == '.') {
  183. return true;
  184. } else {
  185. return false;
  186. }
  187. }
  188. return false;
  189. }
  190. /**
  191. * Returns the root partitians on this system.
  192. */
  193. public File[] getRoots() {
  194. if (!listRootsMethodChecked) {
  195. try {
  196. listRootsMethod = File.class.getMethod("listRoots", noArgTypes);
  197. }
  198. catch (NoSuchMethodException e) {
  199. }
  200. finally {
  201. listRootsMethodChecked = true;
  202. }
  203. }
  204. if (listRootsMethod != null) {
  205. try {
  206. File[] roots = (File[])(listRootsMethod.invoke(null, noArgs));
  207. for(int i = 0; i < roots.length; i++) {
  208. roots[i] = new FileSystemRoot(roots[i]);
  209. }
  210. return roots;
  211. }
  212. catch(Exception e) {
  213. e.printStackTrace();
  214. }
  215. } else {
  216. // System.out.println("File.listRoots doesn't exist");
  217. File[] roots = new File[1];
  218. roots[0] = new File("/");
  219. if(roots[0].exists() && roots[0].isDirectory()) {
  220. return roots;
  221. }
  222. }
  223. return null;
  224. }
  225. }
  226. /**
  227. * FileSystemView that handles some specific windows concepts.
  228. */
  229. class WindowsFileSystemView extends FileSystemView {
  230. private static final Object[] noArgs = {};
  231. private static final Class[] noArgTypes = {};
  232. private static Method listRootsMethod = null;
  233. private static boolean listRootsMethodChecked = false;
  234. /**
  235. * Returns true if the given file is a root.
  236. */
  237. public boolean isRoot(File f) {
  238. if(!f.isAbsolute()) {
  239. return false;
  240. }
  241. String parentPath = f.getParent();
  242. if(parentPath == null) {
  243. return true;
  244. } else {
  245. File parent = new File(parentPath);
  246. return parent.equals(f);
  247. }
  248. }
  249. /**
  250. * creates a new folder with a default folder name.
  251. */
  252. public File createNewFolder(File containingDir) throws IOException {
  253. if(containingDir == null) {
  254. throw new IOException("Containing directory is null:");
  255. }
  256. File newFolder = null;
  257. // Using NT's default folder name
  258. newFolder = createFileObject(containingDir, "New Folder");
  259. int i = 2;
  260. while (newFolder.exists() && (i < 100)) {
  261. newFolder = createFileObject(containingDir, "New Folder (" + i + ")");
  262. i++;
  263. }
  264. if(newFolder.exists()) {
  265. throw new IOException("Directory already exists:" + newFolder.getAbsolutePath());
  266. } else {
  267. newFolder.mkdirs();
  268. }
  269. return newFolder;
  270. }
  271. /**
  272. * Returns whether a file is hidden or not. On Windows
  273. * there is currently no way to get this information from
  274. * io.File, therefore always return false.
  275. */
  276. public boolean isHiddenFile(File f) {
  277. return false;
  278. }
  279. /**
  280. * Returns all root partitians on this system. On Windows, this
  281. * will be the A: through Z: drives.
  282. */
  283. public File[] getRoots() {
  284. if (!listRootsMethodChecked) {
  285. try {
  286. listRootsMethod = File.class.getMethod("listRoots", noArgTypes);
  287. }
  288. catch (NoSuchMethodException e) {
  289. }
  290. finally {
  291. listRootsMethodChecked = true;
  292. }
  293. }
  294. if (listRootsMethod != null) {
  295. try {
  296. File[] roots = (File[])(listRootsMethod.invoke(null, noArgs));
  297. for(int i = 0; i < roots.length; i++) {
  298. roots[i] = new FileSystemRoot(roots[i]);
  299. }
  300. return roots;
  301. }
  302. catch(Exception e) {
  303. e.printStackTrace();
  304. }
  305. } else {
  306. Vector rootsVector = new Vector();
  307. // Create the A: drive whether it is mounted or not
  308. FileSystemRoot floppy = new FileSystemRoot("A" + ":" + "\\");
  309. rootsVector.addElement(floppy);
  310. // Run through all possible mount points and check
  311. // for their existance.
  312. for (char c = 'C'; c <= 'Z'; c++) {
  313. char device[] = {c, ':', '\\'};
  314. String deviceName = new String(device);
  315. File deviceFile = new FileSystemRoot(deviceName);
  316. if (deviceFile != null && deviceFile.exists()) {
  317. rootsVector.addElement(deviceFile);
  318. }
  319. }
  320. File[] roots = new File[rootsVector.size()];
  321. rootsVector.copyInto(roots);
  322. return roots;
  323. }
  324. return null;
  325. }
  326. }
  327. /**
  328. * Fallthrough FileSystemView in case we can't determine the OS.
  329. */
  330. class GenericFileSystemView extends FileSystemView {
  331. private static final Object[] noArgs = {};
  332. private static final Class[] noArgTypes = {};
  333. private static Method listRootsMethod = null;
  334. private static boolean listRootsMethodChecked = false;
  335. /**
  336. * Returns true if the given file is a root.
  337. */
  338. public boolean isRoot(File f) {
  339. if(!f.isAbsolute()) {
  340. return false;
  341. }
  342. String parentPath = f.getParent();
  343. if(parentPath == null) {
  344. return true;
  345. } else {
  346. File parent = new File(parentPath);
  347. return parent.equals(f);
  348. }
  349. }
  350. /**
  351. * creates a new folder with a default folder name.
  352. */
  353. public File createNewFolder(File containingDir) throws IOException {
  354. if(containingDir == null) {
  355. throw new IOException("Containing directory is null:");
  356. }
  357. File newFolder = null;
  358. // Using NT's default folder name
  359. newFolder = createFileObject(containingDir, "NewFolder");
  360. if(newFolder.exists()) {
  361. throw new IOException("Directory already exists:" + newFolder.getAbsolutePath());
  362. } else {
  363. newFolder.mkdirs();
  364. }
  365. return newFolder;
  366. }
  367. /**
  368. * Returns whether a file is hidden or not. Since we don't
  369. * know the OS type, always return false
  370. */
  371. public boolean isHiddenFile(File f) {
  372. return false;
  373. }
  374. /**
  375. * Returns all root partitians on this system.
  376. */
  377. public File[] getRoots() {
  378. if (!listRootsMethodChecked) {
  379. try {
  380. listRootsMethod = File.class.getMethod("listRoots", noArgTypes);
  381. }
  382. catch (NoSuchMethodException e) {
  383. }
  384. finally {
  385. listRootsMethodChecked = true;
  386. }
  387. }
  388. if (listRootsMethod != null) {
  389. try {
  390. File[] roots = (File[])(listRootsMethod.invoke(null, noArgs));
  391. for(int i = 0; i < roots.length; i++) {
  392. roots[i] = new FileSystemRoot(roots[i]);
  393. }
  394. return roots;
  395. }
  396. catch(Exception e) {
  397. e.printStackTrace();
  398. }
  399. } else {
  400. File[] roots = new File[0];
  401. return roots;
  402. }
  403. return null;
  404. }
  405. }
  406. class FileSystemRoot extends File {
  407. public FileSystemRoot(File f) {
  408. super(f,"");
  409. }
  410. public FileSystemRoot(String s) {
  411. super(s);
  412. }
  413. public boolean isDirectory() {
  414. return true;
  415. }
  416. }