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